This question already has answers here:
Why do these list methods (append, sort, extend, remove, clear, reverse) return None rather than the resulting list?
(6 answers)
Closed 6 months ago.
Second list squared each item on list, xs. Running the code below, python gives me 'None'
xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
a = [b**2 for b in xs]
c = (a + xs).sort()
print(c, end=', ')
Same list but different code--
xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
a = [b**2 for b in xs]
c = a + xs
c.sort()
print(c, end=', ')
...python gives me my list(c), all sorted. I don't get it. Or is there a more pythonic way to do this?
Thanks!
Generally speaking, anything that operates on something in-place will return None, by convention. (This convention is not necessarily always followed, however.) somelist.sort() will sort the list in-place.
If you'd rather have a sorted copy, you can just call c = sorted(a + xs). sorted operates on a copy of the original, and therefore returns the copy.
There's a much more through explanation here: http://wiki.python.org/moin/HowTo/Sorting/
You use generator expressions and itertools to reduce the amount of temporary storage like this
>>> import itertools
>>> xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
>>> a = (b**2 for b in xs)
>>> c = sorted(itertools.chain(a, xs))
>>> c
[3, 9, 10, 12, 17, 20, 32, 42, 66, 99, 100, 144, 289, 400, 1024, 1764, 4356, 9801]
Related
I am a beginner in Python . dont know how can i set the order in Dictionary? . i searched and came to know it could be done through from collections import OrderedDict but don't know how to use it. i am trying below mention code to compare two Dictionary but i am not getting the output in order .
d = { k[0]: k[1:] for k in a }
d2= { k[0]: k[1:] for k in b }
p = {i:j for i,j in d2.items() if i not in d}
q = {i:j for i,j in d.items() if i not in d2}
Any idea how to do this ?
Updated Question :
i have a nested list . How to get each list of nested list in next line ?
[['Eth116/1/12 sales connected 1 full 10G Fabric Exte'], ['Eth116/1/13 marketing connected 190 full 100 ']]
Expected Output :
Eth116/1/12 sales connected 1 full 10G Fabric Exte
Eth116/1/13 marketing connected 190 full 100
Dictionaries are unordered and there is not much you can do to change that, short of writing your own subclass of dict (not recommended). Using OrderedDict will work, as shown in hiro protagonists's comment, as long as you keep in mind that the order in an OrderedDict is the order of insertion and is not related to the values of the keys. (The same is true of the ordering of Python 3 dicts.) If a and b have the same elements but in a different order then the resulting OrderedDicts will not be equal, unless you sort a and b beforehand.
If you want to compare two dicts where you can't easily determine the order of insertion, you need a data structure that supports unordered comparisons. I didn't have your data so I had to make some up. I started with this input
>>> a
[[1, 3, 5, 7, 9], [4, 9, 14, 19, 24, 29, 34, 39], [8, 17, 26, 35, 44, 53, 62, 71], [9, 19, 29, 39, 49, 59, 69, 79, 89]]
>>> b
[[1, 3, 5, 7, 9], [4, 9, 14, 19, 24, 29, 34, 39], [8, 17, 26, 35, 44, 53, 62, 71]]
As you can see, a has one extra element beginning 9.
Modify your dictionary construction code to make the values tuples not lists, because the dict values need to be hashable for the next step to work:
>>> d = { k[0]: tuple(k[1:]) for k in a }
>>> d2= { k[0]: tuple(k[1:]) for k in b }
Then you can convert the dictionaries to sets to do an unordered comparison:
>>> s = set(d.items())
>>> s2 = set(d2.items())
>>> s == s2
False
And you can use the set operators to discover what the difference is:
>>> s2 <= s
True
>>> s - s2
set([(9, (19, 29, 39, 49, 59, 69, 79, 89))])
As of python 3.6 dictionaries are ordered in python, ignore the above answer for pythons above that number!
see here, on stackoverflow
I was playing with map() function in Python 3.6.3 when I came across this below situation ::
>>> a = [12, 23, 13, 14, 15, 36]
>>> b = [34, 45, 35, 32, 34, 34]
>>> c = [34, 67, 89, 98, 98, 78]
>>> map(lambda x,y,z:x+y+z, a,b,c )
<map object at 0x0000017DD976EC88>
>>> e=map(lambda x,y,z:x+y+z, a,b,c )
>>> list(e)
[80, 135, 137, 144, 147, 148]
>>> list(e)
[]
My question is that why I cannot get output when I used list(e) second time. It's showing empty list.
Can anyone help me with this?
Because In Python 3, map returns an iterator, which you can only iterate over once. If you iterate over an iterator a second time, it will raise StopIteration immediately, as though it were empty. Thats why you get empty list second time when you call it.
For more info see this question
I hope this helps you! :)
If I have to generate natural numbers, I can use 'range' as follows:
list(range(5))
[0, 1, 2, 3, 4]
Is there any way to achieve this without using range function or looping?
You could use recursion to print first n natural numbers
def printNos(n):
if n > 0:
printNos(n-1)
print n
printNos(100)
Based on Nihal's solution, but returns a list instead:
def recursive_range(n):
if n == 0:
return []
return recursive_range(n-1) + [n-1]
Looping will be required in some form or another to generate a list of numbers, whether you do it yourself, use library functions, or use recursive methods.
If you're not opposed to looping in principle (but just don't want to implement it yourself), there are many practical and esoteric ways to do it (a number have been mentioned here already).
A similar question was posted here: How to fill a list. Although it has interesting solutions, they're all still looping, or using range type functions.
Well, yes, you can do this without using range, loop or recursion:
>>> num = 10
>>> from subprocess import call
>>> call(["seq", str(num)])
You can even have a list (or a generator, of course):
>>> num = 10
>>> from subprocess import check_output
>>> ls = check_output(["seq", str(num)])
>>> [int(num) for num in ls[:-1].split('\n')]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42]
But...what's the purpose?
Is there a way to slice through a whole list while excluding a range of values or multiple range of values in the middle of the list?
For example:
list = [1,2,3,4,5,6,7,8,9,0]
print list[......] #some code inside
I'd like the above code to print the list while excluding a range of values so the output would be: [1,2,3,8,9,0] or excluding multiple value ranges so the output would be: [1,2,6,7,0] by using the slice notation or any other simple method you can suggest.
Use list comprehensions:
>>> mylist = [1,2,3,4,5,6,7,8,9,0]
>>> print [i for i in mylist if i not in xrange(4,8)]
[1, 2, 3, 8, 9, 0]
Or if you want to exclude numbers in two different ranges:
>>> print [i for i in mylist if i not in xrange(4,8) and i not in xrange(1,3)]
[3, 8, 9, 0]
By the way, it's not good practice to name a list list. It is already a built-in function/type.
If the list was unordered and was a list of strings, you can use map() along with sorted():
>>> mylist = ["2", "5", "3", "9", "7", "8", "1", "6", "4"]
>>> print [i for i in sorted(map(int,mylist)) if i not in xrange(4,8)]
[1, 2, 3, 8, 9]
>>> nums = [1,2,3,4,5,6,7,8,9,0]
>>> exclude = set(range(4, 8))
>>> [n for n in nums if n not in exclude]
[1, 2, 3, 8, 9, 0]
Another example
>>> exclude = set(range(4, 8) + [1] + range(0, 2))
>>> [n for n in nums if n not in exclude]
[2, 3, 8, 9]
Using a method, and an exclude list
def method(l, exclude):
return [i for i in l if not any(i in x for x in exclude)]
r = method(range(100), [range(5,10), range(20,50)])
print r
>>>
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
My example uses ranges with ints. But this method can be any list of items, with any number of exclude lists with other items, as long as the items have an equals comparison.
Edit:
A much faster method:
def method2(l, exclude):
'''
l is a list of items, exclude is a list of items, or a list of a list of items
exclude the items in exclude from the items in l and return them.
'''
if exclude and isinstance(exclude[0], (list, set)):
x = set()
map(x.add, [i for j in exclude for i in j])
else:
x = set(exclude)
return [i for i in l if i not in x]
Given my_list = [1,2,3,4,5,6,7,8,9,0], in one line, with enumerate() and range() (or xrange() in Python 2.x):
[n for i, n in enumerate(my_list) if i not in range(3, 7)]
I was wondering if using this was also valid:
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print my_list[:3] + my_list[7:]
Here's a function that takes multiple slice objects and gives you a list containing only the items included by those slices. You can exclude items by specifying around what you want to exclude.
from itertools import chain
def sliceAndDice(sequence, *slices):
return list(chain(*[sequence[slice] for slice in slices]))
So, If you have the list [0,1,2,3,4,5,6,7,8,9] and you want to exclude the 4,5,6 in the middle, you could do this:
sliceAndDice([0,1,2,3,4,5,6,7,8,9], slice(0,4), slice(7,None))
This would return [0, 1, 2, 3, 7, 8, 9].
It works with lists of things that aren't numbers: sliceAndDice(['Amy','John','Matt','Joey','Melissa','Steve'], slice(0,2), slice(4,None)) will leave out 'Matt' and 'Joey', resulting in ['Amy', 'John', 'Melissa', 'Steve']
It won't work right if you pass in slices that are out of order or overlapping.
It also creates the whole list at once. A better (but more complicated) solution would be to create a iterator class that iterates over only the the items you wish to include. The solution here is good enough for relatively short lists.
This question already has answers here:
How to find the cumulative sum of numbers in a list?
(25 answers)
Closed 8 years ago.
can you help me with code which returns partial sum of numbers in text file?
I must import text file, then make a code for partial sums without tools ..etc.
My input:
4
13
23
21
11
The output should be (without brackets or commas):
4
17
40
61
72
I was trying to make code in python, but could only do total sum and not partial one.
If i use the += operator for generator, it gives me an error!
Well, since everyone seems to be giving their favourite idiom for solving the problem, how about itertools.accumulate in Python 3:
>>> import itertools
>>> nums = [4, 13, 23, 21, 11]
>>> list(itertools.accumulate(nums))
[4, 17, 40, 61, 72]
There are a number of ways to create your sequence of partial sums. I think the most elegant is to use a generator.
def partial_sums(iterable):
total = 0
for i in iterable:
total += i
yield total
You can run it like this:
nums = [4, 13, 23, 21, 11]
sums = list(partial_sums(nums)) # [ 4, 17, 40, 61, 72]
Edit To read the data values from your file, you can use another generator, and chain them together. Here's how I'd do it:
with open("filename.in") as f_in:
# Sums generator that "feeds" from a generator expression that reads the file
sums = partial_sums(int(line) for line in f_in)
# Do output:
for value in sums:
print(value)
# If you need to write to a file, comment the loop above and uncomment this:
# with open("filename.out", "w") as f_out:
# f_out.writelines("%d\n" % value for value in sums)
numpy.cumsum will do what you want.
If you're not using numpy, you can write your own.
def cumsum(i):
s = 0
for elt in i:
s += elt
yield s
try this:
import numpy as np
input = [ 4, 13, 23, 21, 11 ]
output = []
output.append(input[0])
for i in np.arange(1,len(input)):
output.append(input[i] + input[i-1])
print output
Use cumulative sum in numpy:
import numpy as np
input = np.array([4, 13, 23, 21 ,11])
output = input.cumsum()
Result:
print output
>>>array([ 4, 17, 40, 61, 72])
Or if you need a list, you may convert output to list:
output = list(output)
print output
>>>[4, 17, 40, 61, 72]
This is an alternative solution using reduce:
nums = [4, 13, 23, 21, 11]
partial_sum = lambda a, b: a + [a[-1] + b]
sums = reduce(partial_sum, nums[1:], nums[0:1])
Pluses in lambda are not the same operator, the first one is list concatenation and the second one is sum of two integers. Altough Blckknght's may be more clear, this one is shorter and works in Python 2.7.
something like this:
>>> lst = [4, 13, 23, 21 ,11]
>>> [sum(lst[:i+1]) for i, x in enumerate(lst)]
[4, 17, 40, 61, 72]