How to convert a list to a list of tuples? - python

I am newbie to Python and need to convert a list to dictionary. I know that we can convert a list of tuples to a dictionary.
This is the input list:
L = [1,term1, 3, term2, x, term3,... z, termN]
and I want to convert this list to a list of tuples (or directly to a dictionary) like this:
[(1, term1), (3, term2), (x, term3), ...(z, termN)]
How can we do that easily in Python?

>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
# Create an iterator
>>> it = iter(L)
# zip the iterator with itself
>>> zip(it, it)
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]
You want to group three items at a time?
>>> zip(it, it, it)
You want to group N items at a time?
# Create N copies of the same iterator
it = [iter(L)] * N
# Unpack the copies of the iterator, and pass them as parameters to zip
>>> zip(*it)

Try with the group clustering idiom:
zip(*[iter(L)]*2)
From https://docs.python.org/2/library/functions.html:
The left-to-right evaluation order of the iterables is guaranteed.
This makes possible an idiom for clustering a data series into
n-length groups using zip(*[iter(s)]*n).

List directly into a dictionary using zip to pair consecutive even and odd elements:
m = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
d = { x : y for x, y in zip(m[::2], m[1::2]) }
or, since you are familiar with the tuple -> dict direction:
d = dict(t for t in zip(m[::2], m[1::2]))
even:
d = dict(zip(m[::2], m[1::2]))

Using slicing?
L = [1, "term1", 2, "term2", 3, "term3"]
L = zip(L[::2], L[1::2])
print L

Try this ,
>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
>>> it = iter(L)
>>> [(x, next(it)) for x in it ]
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]
>>>
OR
>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
>>> [i for i in zip(*[iter(L)]*2)]
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]
OR
>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
>>> map(None,*[iter(L)]*2)
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]
>>>

[(L[i], L[i+1]) for i in xrange(0, len(L), 2)]

The below code will take care of both even and odd sized list :
[set(L[i:i+2]) for i in range(0, len(L),2)]

Related

Python. How to conveniently count the frequence of lists in a collection of lists

I have a list of list.
e.g. list_a = [[1,2,3], [2,3], [4,3,2], [2,3]]
I want to count them like
[1,2,3]: 1
[2,3]: 2
[4,3,2]: 1
There is a library Counter in collections but not for unhashable elements like list. Currently, I just try to use other indirect ways for example transfer the list [1,2,3] into a string "1_2_3" to do that. Is there any other way can enable the count on the list directly?
Not the prettiest way to do it, but this works:
list_a = [[1,2,3], [2,3], [4,3,2], [2,3]]
counts = {}
for x in list_a:
counts.setdefault(tuple(x), list()).append(1)
for a, b in counts.items():
counts[a] = sum(b)
print(counts)
{(2, 3): 2, (4, 3, 2): 1, (1, 2, 3): 1}
A possible approach to do this job is using a dict.
Create a empty dict
Iterate over the list using a for loop.
For each element (iteration), check if the dict contains it.
If it doesn't, save it in the dict as a key. The value will be the occurrence counter.
If it does, just increment its value.
Possible implementation:
occurrence_dict = {}
for list in list_a:
if (occurrence_dict.get(str(list), False)):
occurence_dict[str(list)] += 1
else:
ocorrence_dict[str(list)] = 1
print(occurence_dict)
You can achieve it easily, by using tuple instead of list
c = Counter(tuple(item) for item in list_a)
# or
c = Counter(map(tuple, list_a))
# Counter({(2, 3): 2, (1, 2, 3): 1, (4, 3, 2): 1})
# exactly what you expected
(1, 2, 3) 1
(2, 3) 2
(4, 3, 2) 1
Way 1
Through the indexes of repeatable lists
list_a = [[1,2,3], [2,3], [4,3,2], [2,3], [1,2,3]] # just add some data
# step 1
dd = {i:v for i, v in enumerate(list_a)}
print(dd)
Out[1]:
{0: [1, 2, 3], 1: [2, 3], 2: [4, 3, 2], 3: [2, 3], 4: [1, 2, 3]}
# step 2
tpl = [tuple(x for x,y in dd.items() if y == b) for a,b in dd.items()]
print(tpl)
Out[2]:
[(0, 4), (1, 3), (2,), (1, 3), (0, 4)] # here is the tuple of indexes of matching lists
# step 3
result = {tuple(list_a[a[0]]):len(a) for a in set(tpl)}
print(result)
Out[3]:
{(4, 3, 2): 1, (2, 3): 2, (1, 2, 3): 2}
Way 2
Through converting nested lists to tuples
{i:[tuple(a) for a in list_a].count(i) for i in [tuple(a) for a in list_a]}
Out[1]:
{(1, 2, 3): 2, (2, 3): 2, (4, 3, 2): 1}

Getting the mode from tuples inside lists [duplicate]

How do I convert
[(1,), (2,), (3,)]
to
[1, 2, 3]
Using simple list comprehension:
e = [(1,), (2,), (3,)]
[i[0] for i in e]
will give you:
[1, 2, 3]
#Levon's solution works perfectly for your case.
As a side note, if you have variable number of elements in the tuples, you can also use chain from itertools.
>>> a = [(1, ), (2, 3), (4, 5, 6)]
>>> from itertools import chain
>>> list(chain(a))
[(1,), (2, 3), (4, 5, 6)]
>>> list(chain(*a))
[1, 2, 3, 4, 5, 6]
>>> list(chain.from_iterable(a)) # More efficient version than unpacking
[1, 2, 3, 4, 5, 6]
Here is another alternative if you can have a variable number of elements in the tuples:
>>> a = [(1,), (2, 3), (4, 5, 6)]
>>> [x for t in a for x in t]
[1, 2, 3, 4, 5, 6]
This is basically just a shortened form of the following loops:
result = []
for t in a:
for x in t:
result.append(x)
>>> a = [(1,), (2,), (3,)]
>>> zip(*a)[0]
(1, 2, 3)
For a list:
>>> list(zip(*a)[0])
[1, 2, 3]
>>> a = [(1,), (2,), (3,)]
>>> b = map(lambda x: x[0], a)
>>> b
[1, 2, 3]
With python3, you have to put the list(..) function to the output of map(..), i.e.
b = list(map(lambda x: x[0], a))
This is the best solution in one line using python built-in functions.
You can also use sum function as follows:
e = [(1,), (2,), (3,)]
e_list = list(sum(e, ()))
And it also works with list of lists to convert it into a single list, but you will need to use it as follow:
e = [[1, 2], [3, 4], [5, 6]]
e_list = list(sum(e, []))
This will give you [1, 2, 3, 4, 5, 6]
There's always a way to extract a list from another list by ...for...in.... In this case it would be:
[i[0] for i in e]
Using operator or sum
>>> from functools import reduce ### If python 3
>>> import operator
>>> a = [(1,), (2,), (3,)]
>>> list(reduce(operator.concat, a))
[1, 2, 3]
(OR)
>>> list(sum(a,()))
[1, 2, 3]
>>>
If in python > 3 please do the import of reduce from functools
like from functools import reduce
https://docs.python.org/3/library/functools.html#functools.reduce
You can also unpack the tuple in the list comprehension:
e = [(1,), (2,), (3,)]
[i for (i,) in e]
will still give:
[1, 2, 3]
One Liner yo!
list(*zip(*[(1,), (2,), (3,)]))
In these situations I like to do:
a = [(1,), (2,), (3,)]
new_a = [element for tup in a for element in tup]
This works even if your tuples have more than one element. This is equivalent to doing this:
a = [(1,), (2,), (3,)]
new_a = []
for tup in a:
for element in tup:
new_a.append(element)
If it is already a numpy array, use ravel() method which is more faster than list comprehension.
If it is already a list, list comprehension is better.
Most of the answers above only prints the first element not all the elements
For numpy arrays
#arr = np.array([(1,2), (2,3), (3,4)])
#faster than list comprehension
arr.ravel().tolist()
#output => [1,2,2,3,3,4]
For list
list_ = [(1,2), (2,3), (3,4)]
[x for y in list_ for x in y]
#output => [1,2,2,3,3,4]

Heterogeneous combinations between two lists

What's a better way to generate unique combinations of pairs between two lists where pairs must also be heterogeneous (i.e. pair[0] != pair[1])? By combinations, I mean that I only want one copy of (2, 1) and (1, 2). (is there a better way to express this?)
For example:
a = [1, 4]
b = [1, 2, 3]
magic_functions(a, b)
should return:
[(1, 2), (4, 2), (1, 3), (4, 1), (4, 3)]
I can get there using the following but it seems a bit cumbersome:
prod = itertools.product(a, b)
pairs = set()
for x, y in prod:
if x != y and (y, x) not in pairs:
pairs.add((x, y))
You can use frozenset instead of tuple, a frozenset is immmutable so can be stored in a set:
>>> for x, y in prod:
if x != y:
pairs.add(frozenset((x, y)))
>>> pairs
set([frozenset([1, 3]), frozenset([1, 2]), frozenset([2, 3])])
You can easily extend this to store more than just pairs, for example if we had triads then checking for all of the unique combinations of it in the set will be cumbersome, but frozenset makes it easy:
>>> c = [7, 8, 9]
>>> prod = itertools.product(a, b, c)
>>> triplets = set()
>>> for p in prod:
... f = frozenset(p)
... if len(f) == 3:
... triplets.add(f)
...
>>> triplets
set([frozenset([1, 3, 7]), frozenset([1, 2, 9]), frozenset([8, 1, 2]), frozenset([2, 3, 7]), frozenset([8, 1, 3]), frozenset([1, 2, 7]), frozenset([9, 2, 3]), frozenset([8, 2, 3]), frozenset([1, 3, 9])])
You can use the itertools chain and combinations functions
import itertools
a = [1, 2]
b = [1, 2, 3]
q = set(itertools.chain(a,b))
w = list(itertools.combinations(q,2))
print w
which returns
[(1, 2), (1, 3), (2, 3)]

In Python, how can I create lists that contain a certain index of other lists?

Say I have several lists
A = [1,2,3]
B = [4,5,6]
C = [7,8,9]
How can I create new lists so that they contain matching indexes, as in:
D = [1,4,7]
E = [2,5,8]
F = [3,6,9]
The original lists will always contain the same number of elements, and I need this to work for any number of elements and any number of lists, not just three. I figure I need to loop over a range, but I'm not sure how to go about it.
If I understand you correctly, you may be looking for zip():
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = [7, 8, 9]
>>> zipped = zip(a, b, c)
>>> zipped
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
If instead of several lists, you have a list of the lists that you want to zip, then you can use * for unpacking the sublists, as follows:
>>> myListOfLists = [[1,2,3],[4,5,6],[7,8,9]]
>>> zipped = zip(*myListOfLists)
>>> zipped
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

How to merge lists into a list of tuples?

What is the Pythonic approach to achieve the following?
# Original lists:
list_a = [1, 2, 3, 4]
list_b = [5, 6, 7, 8]
# List of tuples from 'list_a' and 'list_b':
list_c = [(1,5), (2,6), (3,7), (4,8)]
Each member of list_c is a tuple, whose first member is from list_a and the second is from list_b.
In Python 2:
>>> list_a = [1, 2, 3, 4]
>>> list_b = [5, 6, 7, 8]
>>> zip(list_a, list_b)
[(1, 5), (2, 6), (3, 7), (4, 8)]
In Python 3:
>>> list_a = [1, 2, 3, 4]
>>> list_b = [5, 6, 7, 8]
>>> list(zip(list_a, list_b))
[(1, 5), (2, 6), (3, 7), (4, 8)]
In python 3.0 zip returns a zip object. You can get a list out of it by calling list(zip(a, b)).
You can use map lambda
a = [2,3,4]
b = [5,6,7]
c = map(lambda x,y:(x,y),a,b)
This will also work if there lengths of original lists do not match
Youre looking for the builtin function zip.
I am not sure if this a pythonic way or not but this seems simple if both lists have the same number of elements :
list_a = [1, 2, 3, 4]
list_b = [5, 6, 7, 8]
list_c=[(list_a[i],list_b[i]) for i in range(0,len(list_a))]
The output which you showed in problem statement is not the tuple but list
list_c = [(1,5), (2,6), (3,7), (4,8)]
check for
type(list_c)
considering you want the result as tuple out of list_a and list_b, do
tuple(zip(list_a,list_b))
I know this is an old question and was already answered, but for some reason, I still wanna post this alternative solution. I know it's easy to just find out which built-in function does the "magic" you need, but it doesn't hurt to know you can do it by yourself.
>>> list_1 = ['Ace', 'King']
>>> list_2 = ['Spades', 'Clubs', 'Diamonds']
>>> deck = []
>>> for i in range(max((len(list_1),len(list_2)))):
while True:
try:
card = (list_1[i],list_2[i])
except IndexError:
if len(list_1)>len(list_2):
list_2.append('')
card = (list_1[i],list_2[i])
elif len(list_1)<len(list_2):
list_1.append('')
card = (list_1[i], list_2[i])
continue
deck.append(card)
break
>>>
>>> #and the result should be:
>>> print deck
>>> [('Ace', 'Spades'), ('King', 'Clubs'), ('', 'Diamonds')]
Or map with unpacking:
>>> list(map(lambda *x: x, list_a, list_b))
[(1, 5), (2, 6), (3, 7), (4, 8)]
>>>
One alternative without using zip:
list_c = [(p1, p2) for idx1, p1 in enumerate(list_a) for idx2, p2 in enumerate(list_b) if idx1==idx2]
In case one wants to get not only tuples 1st with 1st, 2nd with 2nd... but all possible combinations of the 2 lists, that would be done with
list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
Like me, if anyone needs to convert it to list of lists (2D lists) instead of list of tuples, then you could do the following:
list(map(list, list(zip(list_a, list_b))))
It should return a 2D List as follows:
[[1, 5],
[2, 6],
[3, 7],
[4, 8]]

Categories

Resources