I want to multiply each number of list1 with each number of list2.
For example:
[1,2]*[1,2,3] should return something like this: [1,2,3,2,4,6]
I just want to know if there is any special function to calculate this, as it would take a lot of time to calculate this using a for loop.
A simple nested comprehension will work:
lst1, lst2 = [1, 2], [1, 2, 3]
[x * y for x in lst1 for y in lst2]
# [1, 2, 3, 2, 4, 6]
To get all the pairs (the cartesian product) from the two lists, you can also use itertools.product:
from itertools import product
[x * y for x, y in product(lst1, lst2)]
# [1, 2, 3, 2, 4, 6]
You could also do this using dot products, as provided by numpy (I include this as an answer because you said you are looking for any special function, and are looking to optimize speed, though I agree it's not the most readable or straightforward method):
import numpy as np
lst1, lst2 = [1, 2], [1, 2, 3]
np.dot(np.array([lst1]).T, np.array([lst2])).flatten().tolist()
#[1, 2, 3, 2, 4, 6]
try this:
import itertools
a = [1, 2]
b = [1, 2, 3]
result = []
for n in a:
m = map(lambda x,y: x*y, b, itertools.repeat(n))
result.extend(m)
Related
My target is to get a list of consecutive numbers, repeated accordingly with the initial list values. Lets say I have:
initialList=[1,2,3,5]
And I want to get:
targetList=[0,1,1,2,2,2,3,3,3,3,3]
...I'm totally new with Python, sorry for this -probably- very first steps question. Tried many searchs but the results didn't match with my needs, unfortunately. Thank you very much in advance.
The newbie-friendly solution is to use two loops:
result = []
number = 0
for repeat in initialList:
for _ in range(repeat):
result.append(number)
number += 1
print(result) # [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
If you prefer one-liners for whatever reason, you can combine enumerate and range to get
result = [num for num, repeat in enumerate(initialList) for _ in range(repeat)]
IMO, this is a more maintainable functional solution:
initialList = [1, 2, 3, 5]
def listify(x):
return [x]
# create sub-lists [[0], [1], [2], [3], ...]
sublists = map(listify, range(len(initialList)))
# attach to each sub-list the repititions required [([0], 1), ([2], 2), ...]
sublists_with_rep_spec = zip(sublists, initialList)
# create repetitions based on initialList (using list multiplication)
sublists_with_repetitions = starmap(operator.mul, sublists_with_rep_spec)
# flatten everything out
result = chain.from_iterable(sublists_with_repetitions)
print(list(result))
Note that this is all lazy (on python3) so everything will "happen" only when you actually call list.
Here is another way using repeat and chain.from_iterable
from itertools import repeat, chain
list(chain.from_iterable((repeat(idx, num)) for idx, num in enumerate(initialList)))
[0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
You can use enumerate:
initialList=[1,2,3,5]
final_result = [i for b in [[c]*d for c, d in enumerate(initialList)] for i in b]
Output:
[0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
This is possible via itertools, if you wish to remove the need for nested logic. itertools is part of the standard library.
For improving your understanding of Python, I recommend you see #Ajax1234's solution for some nested list comprehensions.
from itertools import chain
initialList = [1,2,3,5]
targetList = list(chain.from_iterable([i]*j for i, j in enumerate(initialList)))
# [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
Note: you can replace [i]*j with itertools.repeat(i, j) or numpy.repeat(i, j) if you use numpy. The former may be preferable as it is lazy.
Very simple solution using sum and enumerate
initialList = [1, 2, 3, 5]
targetList = sum((times*[index] for index, times in enumerate(initialList)), [])
You can try this approach:
data=[[i]*initialList[i] for i,j in enumerate(initialList)]
print([k for i in data for k in i])
Just for fun I tried with lambda :
initialList=[1,2,3,5]
print(list(map(lambda x:[x]*initialList[x],range(0,len(initialList)))))
lambda result is in nested list.
My solution
>>> initialList=[1,2,3,5]
>>> sum(([num]*count for num, count in enumerate(initialList)), [])
[0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
Another easy way:
from functools import reduce
initialList = [1,2,3,5]
targetList = [[index]*item for index, item in enumerate(initialList)]
targetList = reduce(lambda x,y: x+y, targetList)
print(targetList)
# [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
I find most of the current answers either poor performance-wise or hard to read. An alternative functional way of doing this would be by using such itertools functions as chain.from_iterable, repeat, and count:
from itertools import chain, count, repeat
initial_list = [1, 2, 3, 5]
result = list(chain.from_iterable(map(repeat, count(), initial_list)))
# [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]
I have a list of list of integers:
ls = [[1,2,3],[2,2,3],[1,1,3]]
and I want to end up with a list that has len(ls[0]) elements, and each element is the element that appears most in that index. In this example the result would be [1 (appears in first&last), 2 (appears in first&second), 3 (appears in all)]
I tried using loops and was hoping for a built-in like all (most?)
ls = [[1,2,3],[2,2,3],[1,1,3]]
ls2=[]
ls2 =[item for sub in ls for item in sub]
ls2
Out[40]: [1, 2, 3, 2, 2, 3, 1, 1, 3]
ls3=[]
for item in len(ls):...
What would be the way to do so?
Transpose your list, apply Counters.
>>> from collections import Counter
>>> ls = [[1,2,3],[2,2,3],[1,1,3]]
>>> counts = [Counter(x) for x in zip(*ls)]
>>> [c.most_common(1)[0][0] for c in counts]
[1, 2, 3]
This will pick an arbitrary number if two numbers share the highest occurence for the same index.
my (alternative solution) 2 cents:
>>> ls = [[1, 2, 3], [2, 2, 3], [1, 1, 3]]
>>> l_mc = [max(x, key=x.count) for x in zip(*ls)]
>>> l_mc
[1, 2, 3]
Here is another way:
from collections import Counter
from operator import itemgetter
ls = [[1, 2, 3], [2, 2, 3], [1, 1, 3]]
print([max(x.items(), key = itemgetter(1))[0] for x in map(Counter, zip(*ls))])
# [1, 2, 3]
I am looking to get the difference between two lists.
I am looking for a solution like this only I want to consider non-unique list values.
x = [1, 1, 2, 2, 3]
y = [1, 2]
# i want
z = x - y
# z = [1, 2, 3]
The solution above my code turns the two lists into sets which allows the - operator to work on them but removes non unique values from the lists. Can you think of a simple 'one liner' solution that does what im looking for?
You could use collections.Counter to find the counts of elements in each list. Then you can take the difference and reconstruct a list from the results.
>>> from collections import Counter
>>> x = [1, 1, 2, 2, 3]
>>> y = [1, 2]
>>> [k for _ in range(v) for k,v in (Counter(x) - Counter(y)).iteritems()]
[1, 2, 3]
The drawback being, the order of the result has no real correlation with the order of the input lists. The fact that the result shown above looks sorted is implementation-dependent and possibly only a coincidence.
might not be fancy, first thing that came to mind..
x=[1,1,2,2,3]
y=[1,2]
_ = [ x.remove(n) for n in y if n in x ]
x
[1,2,3]
Here's my take:
x = [1, 1, 2, 2, 3]
y = [1, 2]
z = [n for n in y if (n in x) and x.remove(n)] + x
print(z) # -> [1, 2, 3]
x = [1, 1, 1, 2]
y = [1]
z = [n for n in y if (n in x) and x.remove(n)] + x
print(z) # -> [1, 1, 2]
You just described the union of two sets, so use set:
>>> list(set(x).union(set(y)))
[1, 2, 3]
Is there an easy way to sum all similar values in a list using list comprehensions?
i.e. input:
[1, 2, 1, 3, 3]
expected output:
[6, 2, 2] (sorted)
I tried using zip, but it only works for max 2 similar values:
[x + y for (x, y) in zip(l[:-1], l[1:]) if x == y]
You can use Counter.
from collections import Counter
[x*c for x,c in Counter([1, 2, 1, 3, 3]).items()]
from itertools import groupby
a=[1, 2, 1,1,4,5,5,5,5, 3, 3]
print sorted([sum(g) for i,g in groupby(sorted(a))],reverse=True)
#output=[20, 6, 4, 3, 2]
explantion for the code
first sort the list using sorted(a)
perform groupby to make groupf of similar elements
from each group use sum()
You can use collections.Counter for this, this will take O(N) time.:
>>> from collections import Counter
>>> lst = [1, 2, 1, 3, 3]
>>> [k*v for k, v in Counter(lst).iteritems()]
[2, 2, 6]
Here Counter() returns the count of each unique item, and then we multiply those numbers with their count to get the sum.
I'm sure this question has come up before, but I couldn't find an exact example.
I have 2 lists and want to append the second to the first, only of the values are not already there.
So far I have working code, but was wondering if there were a better, more "Pythonic" was of doing this:
>>> list1
[1, 2, 3]
>>> list2
[2, 4]
>>> list1.extend([x for x in list2 if x not in list1])
>>> list1
[1, 2, 3, 4]
EDIT
Based on comments made, this code does not satisfy adding only once, ie:
>>> list1 = [1,2,3]
>>> list2 = [2,4,4,4]
>>> list1.extend([x for x in list2 if x not in list1])
>>> list1
[1, 2, 3, 4, 4, 4]
How would I end up with only:
[1, 2, 3, 4]
If you want to maintain the order, you can use collections.OrderedDict like this
from collections import OrderedDict
from itertools import chain
list1, list2 = [1, 2, 3], [2, 4]
print list(OrderedDict.fromkeys(chain(list1, list2)))
# [1, 2, 3, 4]
If the order of the elements is not important, you can use the set like this
from itertools import chain
list1, list2 = [1, 2, 3], [2, 4]
print list(set(chain(list1, list2)))
# [1, 2, 3, 4]
A way could be using built in type set:
list(set(list1).union(list2))
You would need to store the result of the operation, if you wanted to extend list1 then you can assign it to list1:
list1=list(set(list1).union(list2))
Note: Keep in mind that this approach may not keep the order of the elements in the list.
Hope this helps!