I have 2 lists of numbers that can be different lengths, for example:
list1 = [1, 2, -3, 4, 7]
list2 = [4, -6, 3, -1]
I need to iterate over these with the function:
final_list = []
for index in range(???):
if list1[index] < 0:
final_list.insert(0, list1[index])
elif list1[index] > 0:
final_list.insert(len(final_list), list1[index])
if list2[index] < 0:
final_list.insert(0, list2[index])
elif list2[index] > 0:
final_list.insert(len(final_list), list2[index])
return final_list
but can't figure out how to deal with the range as the shorter list will become "out of range" if I use the max
length. Any thoughts on how to overcome this or how to change my function?
itertools.zip_longest(*iterables, fillvalue=None)
will do the job for you:
If the iterables are of uneven length, missing values are filled-in with fillvalue.
For your example lists, this will yield:
>>> import itertools
>>> list1 = [1, 2, -3, 4, 7]
>>> list2 = [4, -6, 3, -1]
>>> for combination in itertools.zip_longest(list1, list2):
print(combination)
(1, 4)
(2, -6)
(-3, 3)
(4, -1)
(7, None)
If you only want to use as many values as are present in both lists, use the built-in zip()
:
The iterator stops when the shortest input iterable is exhausted.
>>> for combination in zip(list1, list2):
print(combination)
(1, 4)
(2, -6)
(-3, 3)
(4, -1)
You can process adjacent items from the lists by using itertools.zip_longest()
(itertools.izip_longest()
if using Python 2) to produce a sequence of paired items. Pairs will be padded with None
for lists of mismatched length.
Then you can simplify the code in the body of the loop by flattening the sequence of paired items and filtering out the None
values, and in your case, 0
values. That's what the generator expression below does.
Then it's just a matter of appending or inserting values into final_list
if greater or less than zero respectively.
In code:
from itertools import zip_longest
final_list = []
for value in (i for pair in zip_longest(list1, list2) for i in pair if i):
if value > 0:
final_list.append(value)
else:
final_list.insert(0, value)
print(final_list)
[-1, -3, -6, 1, 4, 2, 3, 4, 7]
Notice that this will filter out any zero values that might be present in the lists. If you want to keep these then modify the generator expression to filter out the None
values only:
(i for pair in zip_longest(list1, list2)
for i in pair if i is not None)
and modify the body of the loop to insert the 0
wherever it should go in final_list
.
In your case you should probably just check if the index is longer than the sequence:
list1 = [1, 2, -3, 4, 7]
list2 = [4, -6, 3, -1]
final_list = []
for index in range(max(len(list1), len(list2))):
if index < len(list1):
if list1[index] < 0:
final_list.insert(0, list1[index])
elif list1[index] > 0:
final_list.insert(len(final_list), list1[index])
if index < len(list2):
if list2[index] < 0:
final_list.insert(0, list2[index])
elif list2[index] > 0:
final_list.insert(len(final_list), list2[index])
print(final_list)
# [-1, -3, -6, 1, 4, 2, 3, 4, 7]
Or use itertools.zip_longest
(or itertools.izip_longest
on python-2.x) and check for some fillvalue (i.e. None
):
import itertools
list1 = [1, 2, -3, 4, 7]
list2 = [4, -6, 3, -1]
final_list = []
for item1, item2 in itertools.zip_longest(list1, list2, fillvalue=None):
if item1 is None:
pass
elif item1 < 0:
final_list.insert(0, item1)
elif item1 > 0:
final_list.append(item1)
if item2 is None:
pass
elif item2 < 0:
final_list.insert(0, item2)
elif item2 > 0:
final_list.append(item2)
However your approach skips items when they are == 0
, that's probably an oversight but you should check that it's working correct with zeros.
Also you use insert
a lot. The last elif
s could instead use final_list.append(item1)
(or item2
), like I did in the second example.
In this case the handling for item1
and item2
is identical, so you could use another loop:
import itertools
list1 = [1, 2, -3, 4, 7]
list2 = [4, -6, 3, -1]
final_list = []
for items in itertools.zip_longest(list1, list2, fillvalue=None):
for item in items:
if item is None:
pass
elif item < 0:
final_list.insert(0, item)
elif item > 0:
final_list.append(item)