Python - iterate over pairs [duplicate] - python

This question already has answers here:
Iterating over every two elements in a list [duplicate]
(22 answers)
Closed 3 years ago.
I have a list [1,2,3,4,5,6] and I want to iterate over it like
[1,2]
[3,4]
[5,6]
I am able to find a lot of answers using zip() that result in
[1,2]
[2,3]
[3,4]
[4,5]
[5,6]
and I could create a new list from this and iterate over every 2nd element in that list with [::2] but I am wondering if there is a more elegant solution.
Thanks for your help.

Using zip with a stride of [::2] is the most concise way I can think to achieve this.
>>> data = [1,2,3,4,5,6]
>>> pairs = [[i,j] for i,j in zip(data[::2], data[1::2])]
>>> pairs
[[1, 2], [3, 4], [5, 6]]

You don't need zip, you can achieve what you want with a simple generator like this:
def pairs(iterable):
for i in range(0, len(iterable), 2):
yield iterable[i:i+2]
Another solution that does not require iterable to be indexable or have a known length, and therefore is more general, is to use iter():
def pairs(iterable):
it = iter(iterable)
while True:
yield next(it), next(it)
This will automatically stop when next() raises StopIteration to indicate that the iterable doesn't have any more items.
In both of the cases you can then do:
for a, b in pairs([1,2,3,4,5,6]):
print(a, b)

Related

Python: Remove every first element in a 2D-List [duplicate]

This question already has answers here:
Get the nth element from the inner list of a list of lists in Python [duplicate]
(1 answer)
Slicing list of lists in Python
(6 answers)
Closed 5 months ago.
i have list in python. For example Test=[[1,1],[1,2],[1,3],[1,4]].
Now i would like to create a 1D-List by removing every first number to get this: [1,2,3,4].
My current Code works just fine, however it is definitely not the most pythonic code.
Could anyone give me a better code for the following? Perhaps a small explenation would be great, as i would like to understand how to programm in good pythonic code. :)
i=len(Test)
b=[]
a=0
for x in range (100):
Test[a].remove(Test[a][0])
b+=Test[a]
a+=1
print(b)
greeting, Dominik
Test=[[1,1],[1,2],[1,3],[1,4]]
# Loop through list using list comprehension and select the second
# item
Test2 = [i[1] for i in Test]
print(Test2)
Using a list comprehension:
test = [[1, 1], [1, 2], [1, 3], [1, 4]]
output = [x[1] for x in test]
print(output) # [1, 2, 3, 4]

Add part of the list to another list in Python [duplicate]

This question already has answers here:
How do I concatenate two lists in Python?
(31 answers)
Closed 2 months ago.
I am trying to understand if it makes sense to take the content of a list and append it to another list.
I have the first list created through a loop function, that will get specific lines out of a file and will save them in a list.
Then a second list is used to save these lines, and start a new cycle over another file.
My idea was to get the list once that the for cycle is done, dump it into the second list, then start a new cycle, dump the content of the first list again into the second but appending it, so the second list will be the sum of all the smaller list files created in my loop. The list has to be appended only if certain conditions met.
It looks like something similar to this:
# This is done for each log in my directory, i have a loop running
for logs in mydir:
for line in mylog:
#...if the conditions are met
list1.append(line)
for item in list1:
if "string" in item: #if somewhere in the list1 i have a match for a string
list2.append(list1) # append every line in list1 to list2
del list1 [:] # delete the content of the list1
break
else:
del list1 [:] # delete the list content and start all over
Does this makes sense or should I go for a different route?
I need something efficient that would not take up too many cycles, since the list of logs is long and each text file is pretty big; so I thought that the lists would fit the purpose.
You probably want
list2.extend(list1)
instead of
list2.append(list1)
Here's the difference:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = [7, 8, 9]
>>> b.append(a)
>>> b
[4, 5, 6, [1, 2, 3]]
>>> c.extend(a)
>>> c
[7, 8, 9, 1, 2, 3]
Since list.extend() accepts an arbitrary iterable, you can also replace
for line in mylog:
list1.append(line)
by
list1.extend(mylog)
To recap on the previous answers. If you have a list with [0,1,2] and another one with [3,4,5] and you want to merge them, so it becomes [0,1,2,3,4,5], you can either use chaining or extending and should know the differences to use it wisely for your needs.
Extending a list
Using the list classes extend method, you can do a copy of the elements from one list onto another. However this will cause extra memory usage, which should be fine in most cases, but might cause problems if you want to be memory efficient.
a = [0,1,2]
b = [3,4,5]
a.extend(b)
>>[0,1,2,3,4,5]
Chaining a list
Contrary you can use itertools.chain to wire many lists, which will return a so called iterator that can be used to iterate over the lists. This is more memory efficient as it is not copying elements over but just pointing to the next list.
import itertools
a = [0,1,2]
b = [3,4,5]
c = itertools.chain(a, b)
Make an iterator that returns elements from the first iterable until it is exhausted, then proceeds to the next iterable, until all of the iterables are exhausted. Used for treating consecutive sequences as a single sequence.
Take a look at itertools.chain for a fast way to treat many small lists as a single big list (or at least as a single big iterable) without copying the smaller lists:
>>> import itertools
>>> p = ['a', 'b', 'c']
>>> q = ['d', 'e', 'f']
>>> r = ['g', 'h', 'i']
>>> for x in itertools.chain(p, q, r):
print x.upper()
You can also combine two lists (say a,b) using the '+' operator.
For example,
a = [1,2,3,4]
b = [4,5,6,7]
c = a + b
Output:
>>> c
[1, 2, 3, 4, 4, 5, 6, 7]
That seems fairly reasonable for what you're trying to do.
A slightly shorter version which leans on Python to do more of the heavy lifting might be:
for logs in mydir:
for line in mylog:
#...if the conditions are met
list1.append(line)
if any(True for line in list1 if "string" in line):
list2.extend(list1)
del list1
....
The (True for line in list1 if "string" in line) iterates over list and emits True whenever a match is found. any() uses short-circuit evaluation to return True as soon as the first True element is found. list2.extend() appends the contents of list1 to the end.
You can simply concatnate two lists, e.g:
list1 = [0, 1]
list2 = [2, 3]
list3 = list1 + list2
print(list3)
>> [0, 1, 2, 3]
Using the map() and reduce() built-in functions
def file_to_list(file):
#stuff to parse file to a list
return list
files = [...list of files...]
L = map(file_to_list, files)
flat_L = reduce(lambda x,y:x+y, L)
Minimal "for looping" and elegant coding pattern :)
you can use __add__ Magic method:
a = [1,2,3]
b = [4,5,6]
c = a.__add__(b)
Output:
>>> c
[1,2,3,4,5,6]
If we have list like below:
list = [2,2,3,4]
two ways to copy it into another list.
1.
x = [list] # x =[] x.append(list) same
print("length is {}".format(len(x)))
for i in x:
print(i)
length is 1
[2, 2, 3, 4]
2.
x = [l for l in list]
print("length is {}".format(len(x)))
for i in x:
print(i)
length is 4
2
2
3
4

List.extend() is not working as expected in Python [duplicate]

This question already has answers here:
Why can't I iterate twice over the same iterator? How can I "reset" the iterator or reuse the data?
(5 answers)
Closed 4 years ago.
I have a list queueand an iterator object neighbors whose elements I want to append to the list.
queue = [1]
neighbor = T.neighbors(1) #neighbor is a <dict_keyiterator at 0x16843d03368>
print(list(neighbor)) #Output: [2, 3]
queue.extend([n for n in neighbor])
print(queue)
Output:
[1]
Expected Output:
[1, 2, 3]
What is going wrong?
You already exhaust the iterator neighbor when you use it in the list constructor for printing, so it becomes empty in the list comprehension in the next line.
Store the converted list in a variable so you can both print it and use it in the list comprehension:
queue = [1]
neighbor = T.neighbors(1) #neighbor is a <dict_keyiterator at 0x16843d03368>
neighbors = list(neighbor)
print(neighbors) #Output: [2, 3]
queue.extend([n for n in neighbors])
print(queue)
You consumed the iterator already:
print(list(neighbor))
Take that line out.

Elegant Way of Ignoring Specific Python ListElements [duplicate]

This question already has answers here:
Get unique values from a list in python [duplicate]
(30 answers)
Closed 6 years ago.
I have recently started trying to learn Python, and I try to improve the way I write code, and make it more "Pythonic".
Therefore, it would really be nice if someone could explain to me if the following can be formulated more elegantly.
Hopefully this is not a duplicate (I checked, but you never know)
I have a list of 5 elements, and I want to return specific elements.
Let's say for example that I have [1, 2, 3, 3, 4].
I already have a function double(list), that if a list element exists twice returns that element (in this case 3).
I would like to generate from this list a tuple that contains the numbers that are exist only once (1, 2, 4).
One option is the following:
Run the double(list) function and get the value of the element that is double.
Create an empty tuple
Iterate over the list items, and if the value is not equal to what the double(list) function returned, add it to the tuple
Return the tuple.
My question is: is there a more elegant/Pythonic way of doing this?
(in one line, using maybe a more complex expression?)
Thanks in advance
The general way to do this is to make a set out of the elements and then count them, or just use collections.Counter, then go through the list and include only the appropriate elements, by either creating an empty list and then adding to it with a traditional loop or by using a comprehension with a filter.
>>> import collections
>>> l = [1, 2, 3, 3, 4]
>>> c = collections.Counter(l)
>>> new_list = [item for item in l if c[item] < 2]
>>> new_list
[1, 2, 4]
Since you want a single-line solution (well except for the actual list declaration of course :) ):
your_list = [1, 2, 3, 3, 4]
uniques = [item for item in your_list if your_list.count(item) == 1]
I would use collections.Counter for that:
>>> import collections
>>> l = [1, 2, 3, 3, 4]
>>> c = collections.Counter(l)
>>> [el for el in l if c[el] == 1]
[1, 2, 4]

Flatten a list in python [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 6 months ago.
I have a list like this:
[[(video1,4)], [(video2,5),(video3,8)], [(video1,5)], [(video5, 7), (video6,9)]...]
each item in this list may contain a single data pair, or a tuple, I want to change this list into
[(video1,4),(video2,5),(video3,8),(video1,5),(video5,7),(video6,9)...]
then do this:
for item in list:
reqs = reqs + item[1]
b.append(item[0])
c = set(b)
I don't know how to change the list structure, or how to do the same calculation based on the original list?
There is a very simple way of doing this with list comprehensions. This example has been documented in the python documentation here
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Here is the solution that you would want to implement. As per your example, this is the simplest solution
In [59]: your_list = [[('video1',4)], [('video2',5),('video3',8)], [('video1',5)], [('video5', 7), ('video6',9)]]
In [60]: improved_list = [num for elem in your_list for num in elem]
In [61]: improved_list
Out[61]:
[('video1', 4),
('video2', 5),
('video3', 8),
('video1', 5),
('video5', 7),
('video6', 9)]
If this list is singly-nested (list of lists) you can do this, which I use a lot:
flat_list = sum(list_of_lists, [])
This works due to the fact that sum simply adds up the lists, and adding up lists works in python as expected :)
Note: This is inefficient and some say unreadable.
If you just want to flatten the list, just use itertools.chain.from_iterable: http://docs.python.org/library/itertools.html#itertools.chain.from_iterable
To flatten one level, you can use itertools.chain.from_iterable():
flattened_list = itertools.chain.from_iterable(my_list)
Here's another one (no libraries):
def plus(a,b): return a + b
reduce(plus, your_list)
Try this:
from itertools import chain
c = set()
reqs = 0
for vid, number in chain(*your_list):
c.add(vid)
reqs += number
Also see related post Flattening a shallow list in Python.
There should be negligible performance increase from using chain.from_iterable(list) rather than chain(*list), but it's true that the former looks cleaner.
to extract all tuples from a data structure ...
def get_tups(y):
z = []
if y:
for x in y:
if isinstance(x, tuple):
z.append(x)
else:
z.extend(get_tups(x))
return z
maybe ...

Categories

Resources