Flatten a list in python [duplicate] - python

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 ...

Related

Python - iterate over pairs [duplicate]

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)

Inserting entries in a list without sorting the output [duplicate]

This question already has answers here:
Combining two sorted lists in Python
(22 answers)
Closed 4 years ago.
I have two lists as follows:
l1 = [1,3,5,7] and l2 = [2,4,6]
how can I get this output l3 = [1,2,3,4,5,6,7] ,that is, inserting the first entry from l2 as second entry in l1 and so on. Thanks in advance
Here is one way that relies on the input lists being sorted in advance in an alternating order like your example, such that you actually want to intercalate them, rather than doing any type of sorted merge.
And that the value None would never serve as a true value among your lists.
In [12]: from itertools import chain, ifilter, izip_longest
In [13]: list(ifilter(lambda x: x is not None, chain(*izip_longest(l1, l2))))
Out[13]: [1, 2, 3, 4, 5, 6, 7]
Without assuming the input lists are sorted, or requiring the output be sorted, you can use itertools for this.
from itertools import zip_longest, chain
l1 = [1,3,5,7]
l2 = [2,4,6]
res = list(filter(None, chain.from_iterable(zip_longest(l1, l2))))
# [1, 2, 3, 4, 5, 6, 7]
Explanation
Use zip_longest to iterate lists of unequal length pairwise.
Use chain.from_iterable to efficiently chain the list of lists.
Use filter(None, ...) to remove the final None element.

Simple way of excluding an element from a calculation on a list?

For example I want to check the correlation coefficient between two lists like:
r = np.corrcoef(list25, list26)[0,1]
but I want to exclude -1's in the lists from the calculation. Is there a simple one-liner way of doing this instead of making a new copies of the lists and iterating through to remove all -1's and such?
There is a one liner solution. It's creating a new list without the ones. It can be done using List Comprehension:
new_list = [x for x in old_list if x != -1]
it basically copies everything that matches the condition from the old list to the new list.
So, for your example:
r = np.corrcoef([x for x in list25 if x != -1], [x for x in list26 if x != -1])[0,1]
Use a generator
def greater_neg_1(items):
for item in items:
if item>-1:
yield item
Usage:
>>> L = [1,-1,2,3,4,-1,4]
>>> list(greater_neg_1(L))
[1, 2, 3, 4, 4]
or:
r = np.corrcoef(greater_neg_1(list25), greater_neg_1(list26))[0,1]
Won't require any extra memory.
If you actually want to remove the -1 from the lists:
while -1 in list25: list25.remove(-1)

Extracting first elements from a list of tuples using list comprehension [duplicate]

This question already has answers here:
How to get first element in a list of tuples?
(17 answers)
Closed 2 years ago.
I have a list of tuples of which I want to extract the first element of each tuple to another list.
I had a list of tuples called lst and tried to extract the elements to a list called lst2 and what I got was:
>>> lst = [(1, 2), (3, 4), (5, 6)]
>>> lst2 = []
>>> [lst2[i] = lst[i][0] for i in range(len(lst))]
File "<stdin>", line 1
[lst2[i] = lst[i][0] for i in range(len(list))]
^
SyntaxError: invalid syntax
The desired output is [1, 3, 5].
Can you help figure out what's wrong with this syntax?
Using lst and lst2 as the variable names as others have noted list is a bad choice.
You don't need the index. Using the index is often considered bad form.
lst2 = [ pair[0] for pair in lst]
If you really, really need the index, for some math or something.
lst2 = [ lst[i][0] for (i, pair) in enumerate(lst)]
If you need to manipulate 2 dimensional matrices of numbers, you might want to learn about numpy and look at numpy.matrix and numpy.array.
Inside the list comprehension, only expression can come. list2[i] = list[i][0] is an assignment statement.
And, you don't need to use indexes to access items. Just iterate the list.
>>> lst = [ (1,2), (3,4), (5,6)]
>>> lst2 = [x[0] for x in lst]
>>> lst2
[1, 3, 5]
BTW, don't use list as a variable name. It shadows builtin type/function list.
You can't set a variable using the equals operator while looping through a list in one line. You could simply do it like this:
list = [ (1,2), (3,4), (5,6)]
list2 = []
[list2.append(list[i]) for i in range(len(list))]
Another way to do this is with zip():
>>> lst = [(1,2), (3,4), (5,6)]
>>> zip(*lst)
[(1, 3, 5), (2, 4, 6)]
>>> zip(*lst)[0]
(1, 3, 5)
>>> list(zip(*lst)[0])
[1, 3, 5]
However, it is a little wasteful when you only need the one list.

Adding a constant tuple value to a list of tuples

I have a list of tuples (each tuple item is a pair of integers) and I would like to add a constant value to each tuple in the list.
For example
[(x0,y0),(x1,y1),...] -> [(x0+xk,y0+yk),(x1+xk,y1+yk)....]
xk,yk are constants
How do I do this
Thanks
Use numpy, e.g.,
>>> import numpy as np
>>> a = np.array([[1,2],[2,3]])
>>> print a
[[1 2]
[2 3]]
>>> print a + 2
[[3 4]
[4 5]]
>>>> l = [(1,2), (3,4)]
>>>> for i, e in enumerate(l):
.... l[i] = (e[0]+xk, e[1]+yk)
As always, untested. ;-)
If you don't need to do it in place, it's even simpler
>>>> l = [(e[0]+xk, e[1]+yk) for e in l]
You can't add a constant to a tuple because tuples are immutable.
You can however create a new tuple from the old one by incrementing it's values. See jae's answer for the basics of how to do this.
You should note however that you will be creating a lot of new tuples in this loop and this may not be a very efficient way of handling this. You should investigate numpy (as suggested by nikow) or perhaps using lists or coordinate objects instead of tuples.
an example to add things to tuple
>>> a=(1,2)
>>> a+=(1,)
>>> a
(1, 2, 1)
you can adapt it to your requirement
Solution:
l = [(i[0]+k[0], i[1]+k[1]) for i in l]
Test code:
l = [(1,2), (3,4)]
k = (10, 100)
l = [(i[0]+k[0], i[1]+k[1]) for i in l]
assert l == [(11, 102), (13, 104)]

Categories

Resources