Related
I have 2 lists, for example:
list1 = [1, 2, 2, 3, 3, 4]
list2 = [1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5]
I want to get a list 3 which will include all numbers from list2 matching the numbers from list1:
list3 = [1, 1, 2, 2, 3, 3, 4, 4, 4]
I was trying to use 2 while loops to go through list1 and list2 and match numbers, but it gives me wrong number of values:
listO = [1, 2, 2, 3, 3, 4]
listX = [1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5]
x_temp = []
a = 0
b = 0
while a < len(listO):
while b < len(listX):
if listO[a] == listX[b]:
x_temp.append(listX[b])
print("Outlier a:" , listO[a] )
listX.remove(listX[b])
b+=1
b=0
a+=1
list3 = [1, 2, 2, 3, 3, 4, 4]
Is there any way to do it using loops?
Please do NOT provide solution using set() it doesn`t work for my lists!
With a for loop:
listO = [1, 2, 2, 3, 3, 4]
listX = [1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5]
x_temp = []
for x in listX:
if x in listO:
x_temp.append(x)
# [1, 1, 2, 2, 3, 3, 4, 4, 4]
You can use a list comprehension for this.
list1 = [1, 2, 2, 3, 3, 4]
list2 = [1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5]
list3 = [i for i in list2 if i in list1]
# [1, 1, 2, 2, 3, 3, 4, 4, 4]
I am breaking my head around this small issue which I am sure can (and should) be solved recursively.
# split list in sublists based on length of first element.
list = [3, 1, 2, 3, 4, 1, 2, 3, 4]
#* #*
# *number of elements of the sublist
It is better shown than explained, the above should result to:
[[1, 2, 3], [1, 2, 3, 4]]
The lists I am processing always respect this logic, the first element is always the length of the following n elements.
EDIT:
Based on some of the suggestions, I simply added a yield to get it done lazily.
def split(ls):
"""
func that given a list extracts sub lists with the length indicated by the first element
[2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4] => [[1, 2], [1, 2, 3], [1, 2, 3, 4]]
"""
res = []
while ls:
dim = ls[0]
yield ls[1:dim + 1]
ls = ls[dim + 1:]
return res
>>> list(split([2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4]))
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]
Simple slicing will do:
>>> a = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> c = []
>>> while len(a) :
... b = a[0]
... c.append( a[1:b+1] )
... a = a[b+1:]
...
>>> c
[[1, 2, 3], [1, 2, 3, 4]]
Here is a way to achieve what you want:
numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4]
result = []
def split_list(list_):
first = list_.pop(0)
result.append(list_[:first])
if len(list_[first:]) > 0:
split_list(list_[first:])
split_list(numbers)
print(result)
You can use itertools.islice here.
>>> from itertools import islice
>>> lst = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> def chunks(lst):
... t=iter(lst)
... c=next(t,None)
... while c:
... yield list(islice(t,None,c))
... c=next(t,None)
...
>>> list(chunks(lst))
[[1, 2, 3], [1, 2, 3, 4]]
I've edited my answer as inspired by someone else's in this thread. This doesn't consume the original array and uses recursion instead of looping.
numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4, 3,1,1,1,1]
def do_take(numbers: []):
result = []
to_take = numbers[0]
result.append(numbers[1:to_take + 1])
if len(numbers) > to_take:
result.append(do_take(numbers[to_take + 1:]))
return result
print(do_take(numbers))
print(numbers)
Results in the following output:
# python /tmp/breakup.py
[[1, 2, 3], [[1, 2, 3, 4], [[1, 1, 1], [[]]]]]
[3, 1, 2, 3, 4, 1, 2, 3, 4, 3, 1, 1, 1, 1]
I know how to get ALL combinations of a list in Python with itertools, but what if I want to limit the amount of repeats?
So, if I have [1, 2, 3, 4, 5]
But I want to limit combinations to only 3 repeats of each item (with a fixed length of the final list, say 10):
[1, 1, 1, 2, 3, 3, 5, 5, 5, 4]
[1, 2, 3, 3, 3, 4, 5, 5, 4, 4]
[4, 4, 1, 1, 1, 5, 2, 2, 2, 3]
and so on. How do I do this?
This would work:
import random
L = [1, 2, 3, 4, 5]
L3 = L * 3
random.shuffle(L3)
L3[:10]
I don't know if there is a more elegant way but that seems to work:
from itertools import combinations_with_replacement
a = [1, 2, 3, 4, 5] # can contain letters as well
all_combinations = combinations_with_replacement(a, 10)
filtered_results = []
for current in all_combinations:
throw_away = False
for item in current:
if current.count(item) > 3:
throw_away = True
break
if not throw_away:
filtered_results.append( current )
for j in filtered_results:
print(j)
You could do it the following way: Use [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5] and use itertools.combination(the list from above, 10). That would mean that each element occurs at most three times in a resulting list.
Example with smaller list:
Edited to ensure every combination occurs exactly once, the combinations occur in random order and, finally, every combination has a random order.
Also incorporated the idea of Mike Müller to just multiply the list by 3.
import itertools
import random
combinations = set()
for c in itertools.combinations(sorted([1, 2, 3] * 3), 5):
combinations.add(c)
shuffledCombinations = list(combinations)
random.shuffle(shuffledCombinations)
for combination in shuffledCombinations:
copiedCombination = list(combination)
random.shuffle(copiedCombination)
print copiedCombination
which will give:
[2, 1, 3, 2, 2]
[2, 2, 1, 1, 2]
[3, 3, 3, 1, 2]
[2, 2, 3, 2, 3]
[1, 2, 3, 1, 2]
[1, 1, 1, 2, 3]
[2, 1, 1, 1, 2]
[3, 3, 1, 1, 1]
[1, 3, 3, 3, 1]
[3, 2, 3, 2, 3]
[3, 2, 1, 2, 3]
[1, 1, 2, 3, 3]
Let's say I have a list of 5 elements x=[a,b,c,d,e] and I want to run a for loop that prints all lists where two of the entries are 1 less than the corresponding entries in the original list.
What is a simple way to do this in Python? Thanks in advance.
Edit: if x=[4,5,6,7,8] I want:
[3,4,6,7,8], [3,5,5,7,8], [3,5,6,6,8] etc.
Something like this:
>>> from itertools import combinations
>>> lis = [0,1,2,3,4]
>>> for x,y in combinations(range(len(lis)),2):
l = lis[:]
l[x] -= 1
l[y] -= 1
print l
...
[-1, 0, 2, 3, 4]
[-1, 1, 1, 3, 4]
[-1, 1, 2, 2, 4]
[-1, 1, 2, 3, 3]
[0, 0, 1, 3, 4]
[0, 0, 2, 2, 4]
[0, 0, 2, 3, 3]
[0, 1, 1, 2, 4]
[0, 1, 1, 3, 3]
[0, 1, 2, 2, 3]
Shorter version:
for x,y in combinations(range(len(lis)),2):
print [item - 1 if i in (x,y) else item for i,item in enumerate(lis)]
...
[-1, 0, 2, 3, 4]
[-1, 1, 1, 3, 4]
[-1, 1, 2, 2, 4]
[-1, 1, 2, 3, 3]
[0, 0, 1, 3, 4]
[0, 0, 2, 2, 4]
[0, 0, 2, 3, 3]
[0, 1, 1, 2, 4]
[0, 1, 1, 3, 3]
[0, 1, 2, 2, 3]
from itertools import combinations
a = [1,2,3,4]
for combination in combinations(range(len(a)),r=2):
print [c-(1 if i in combination else 0) for i,c in enumerate(a)]
I have a problem where I want to have a nested for loop concatenate a string. For some reason I'm not getting the correct output. Can someone give me some advice? This should be simple.
newRow = []
matrix = []
for i in range(0,3):
for j in range(0,5):
newRow.append(j)
matrix.append(newRow)
print matrix
python test.py
[[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4],
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4],
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]]
I want it to print...
[[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]]
You keep adding to the same newRow. If you want to get a clean row, you need to create an empty one on each iteration:
matrix = [] newRow = [] <- the same array
for i in range(0,3): matrix = []
newRow = [] <- a new array for i in range(0,3):
for j in range(0,5): instead of for j in range(0,5):
newRow.append(j) newRow.append(j)
matrix.append(newRow) matrix.append(newRow)
There are, of course, more pythonic ways of achieving this, but I'm trying to point out what the problem with the code is.
You can make this if you want nested loop:
matrix = [ [ i for i in range(5)] for j in range(3)]
print matrix
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
matrix = []
for i in range(0,3):
matrix.append(list(range(0, 5)))
or even:
matrix = [list(range(0, 5)) for i in range(0, 3)]
You are close, its just a matter of properly scoping:
matrix = []
for i in range(0,3):
newRow = []
for j in range(0,5):
newRow.append(j)
matrix.append(newRow)
print matrix
Whatever you do,
DON'T DO THIS
DON'T DO THIS
DON'T DO THIS:
>>> x = [range(0,5)]*3
>>> x
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
>>> x[0][0] = 'LOL'
>>> x
[['LOL', 1, 2, 3, 4], ['LOL', 1, 2, 3, 4], ['LOL', 1, 2, 3, 4]]
use a list comprehension.