import itertools
list_with_tuples=[(1,), (2,), (3,)]
pairs = itertools.combinations(list_with_tuples, 2)
for pair in pairs:
print(pair)
so the result of pairs is :
((1,),(2,)) ,
((1,),(3)) ,
((2,),(3,))
How I can union them?
After union I want to do a dictionary like:
di={ (1,2): value1, (1,3): value2, (2,3): value3 }
How can I do this?
One way to "union" tuples in python is to simply add them:
>>> (1,) + (2,)
(1, 2)
So you can modify your example to add:
import itertools
list_with_tuples=[(1,), (2,), (3,)]
pairs = itertools.combinations(list_with_tuples, 2)
for left, right in pairs:
print(left + right)
Outputs:
(1, 2)
(1, 3)
(2, 3)
If you need to add n tuples, rather than just 2 of them, you can use sum and specify an initial value of the empty tuple () as the second argument.
Alternatively, as Kevin mentioned in the comments, you can build a new tuple by consuming the output of an itertools.chain, which will likely be more efficient if n is large.
You can use a dict comprehension to do this for you. Iterate over the itertools.combinations, index out the values from the tuple, then create your new tuple as the key and add them for the value.
>>> {(i[0],j[0]) : i[0] + j[0] for i,j in itertools.combinations(list_with_tuples, 2)}
{(1, 2): 3, (1, 3): 4, (2, 3): 5}
You can chain the elements into a single tuple:
from itertools import chain,combinations
list_with_tuples=[(1,), (2,), (3,)]
di = {tuple(chain.from_iterable(comb)):"value" for comb in combinations(list_with_tuples, 2)}
print(di)
{(1, 2): 'value', (1, 3): 'value', (2, 3): 'value'}
It will work for any length combinations.
If you have a another container that has the values you can zip:
from itertools import chain,combinations
list_with_tuples=[(1,), (2,), (3,)]
values = [1,2,3]
di = {tuple(chain.from_iterable(comb)): val for comb,val in zip(combinations(list_with_tuples, 2),values)}
print(di)
{(1, 2): 1, (1, 3): 2, (2, 3): 3}
You can join iterable objects such as tuples and lists together using itertools.chain():
list_with_tuples=[(1,), (2,), (3,)]
pairs = itertools.combinations(list_with_tuples, 2)
for pair in pairs:
print(tuple(itertools.chain(*pair)))
This also has the advantage of being lazy, so you can iterate over the chain one element at a time instead of making a full tuple out of it, if that's what you need. If pair is also a lazy iterator, you probably want to use itertools.chain.from_iterable() instead of the star operator.
Related
I have two lists:
a = [2,3,1,4]
b=[two, three, one, four]
I need to sort the first list in ascending order, but I need the second list ( made up of strings) to follow the same sorting.
That is, I expect to get the following result:
a = [1,2,3,4]
b = [one, two, three, four]
does anyone have a simple way to do this?
aa, bb = zip(*sorted(zip(a, b)))
BTW, you will need to quote the items in the second list, unless those are variable references.
The inner zip puts the two lists together into one tuple:
[(2, 'two'), (3, 'three'), (1, 'one'), (4, 'four')]
The sorted does the sort. Tuples sort by their first key:
[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
The outer zip & * operator usage is an "unzip a list" pythonic trick.
Use: sorted(zip(a,b))
We are basically zipping the two lists together. They need to have same length.
Combine the two lists into a list of two-element tuples and sort it:
mylist = [
(2, "two"),
(3, "three"),
(1, "one"),
(4, "four")
]
mylist.sort()
It will be sorted in order of the first element.
I'm trying to use the built-in function enumerate() to label some points or vertices where each point is represented by its coordinates in a list(or set) of tuples which essentially looks like {(4,5), (6,8), (1,2)}
I want to assign a letter starting from "a" in ascending order to each tuple in this set, using enumerate() does exactly the same but It's written in a way that it returns the value of the index of each item so that it's a number starting from 0.
is there any way to do it other than writing my own enumerate()?
Check this out:
import string
tup = {(4,5), (6,8), (1,2)}
dic = {i: j for i, j in zip(string.ascii_lowercase, tup)}
This returns:
{'a': (4, 5), 'b': (6, 8), 'c': (1, 2)}
This is enumerate's signature.
enumerate(iterable, start=0)
Use start as 65 for 'A' and 97 for 'a'.
lst=[(1,2),(2,3),(3,4),...]
for idx,val in enumerate(lst,65):
print(chr(idx),val)
A (1, 2)
B (2, 3)
C (3, 4)
Maybe this is a way to get what you want, using chr():
L = [(4,5), (6,8), (1,2)]
for k, v in enumerate(L):
print(chr(65 + k), v)
Output :
A (4, 5)
B (6, 8)
C (1, 2)
The enumerate function is defined as follow :
enumerate(iterable, start=0)
I think just have to write your own enumerate or an wrapper around enumerate.
In python, I wish to sort tuples based on the value of their last element. For example, i have a tuple like the one below.
tuples = [(2,3),(5,7),(4,3,1),(6,3,5),(6,2),(8,9)]
which after sort I wish to be in this format.
tuples = [(4,3,1),(6,2),(2,3),(6,3,5),(5,7),(8,9)]
How do i get to doing that?
Povide list.sort with an appropriate key function that returns the last element of a tuple:
tuples.sort(key=lambda x: x[-1])
You can use:
from operator import itemgetter
tuples = sorted(tuples, key=itemgetter(-1))
The point is that we use key as a function to map the elements on an orderable value we wish to sort on. With itemgetter(-1) we construct a function, that for a value x, will return x[-1], so the last element.
This produces:
>>> sorted(tuples, key=itemgetter(-1))
[(4, 3, 1), (6, 2), (2, 3), (6, 3, 5), (5, 7), (8, 9)]
I have a dictionary where each key is a tuple of values, I want to use the sorted() method to sort the dictionary on the very first element of my tuple. My code looks like this:
def mapData(header_list, dict_obj):
master_dict = {}
client_section_list = []
for element in header_list:
for row in dict_obj:
if (row['PEOPLE_ID'], row['DON_DATE']) == element:
client_section_list.append(row)
element = list(element)
element_list = [client_section_list[0]['DEDUCT_AMT'],
client_section_list[0]['ND_AMT'],
client_section_list[0]['DEDUCT_YTD'],
client_section_list[0]['NONDEDUCT_YTD']
]
try:
element_list.append((float(client_section_list[0]['DEDUCT_YTD']) +
float(client_section_list[0]['NONDEDUCT_YTD'])
))
except ValueError:
pass
element.extend(element_list)
element = tuple(element)
master_dict[element] = client_section_list
client_section_list = []
return sorted(master_dict, key=lambda key: key[master_dict[(1)]]
The last line is where I'm trying to find a way to sort it. My tuple looks like this:
(312178078,6/22/15,25,0,25,0,25.0)
Not entirely sure what you are trying to do, particularly what that function is supposed to return. I assume that you want to return the dictionary sorted by the first element in the key-tuples.
For this, there are two things to note:
Tuples are by default sorted by their first element (and if those are the same, then by the second, and so on), so no special key function is required
Regular dictionaries are unordered, i.e. they can not be permanently sorted in any order; you can only sort their items as a list, or use that list to create an OrderedDict instead
Some minimal example:
>>> d = {(2,4): 1, (1,3): 2, (1,2): 3, (3,1): 4}
>>> sorted(d)
[(1, 2), (1, 3), (2, 4), (3, 1)]
>>> sorted(d.items())
[((1, 2), 3), ((1, 3), 2), ((2, 4), 1), ((3, 1), 4)]
>>> collections.OrderedDict(sorted(d.items()))
OrderedDict([((1, 2), 3), ((1, 3), 2), ((2, 4), 1), ((3, 1), 4)])
In your case, you probably want this:
return collections.OrderedDict(sorted(master_dict.items()))
As #tobias_k has mentioned, sorted sorts tuples by its elements with decreasing priority, e.g. if you take a tuple (a, b, c) the highest sorting priority goes to a, then goes b etc (by default sorted uses object's comparison methods and this is how tuple comparison works). So sorted(master_dict) is all you need if you want a list of sorted keys, yet I believe you really want to leave the values
sorted(master_dict.items(), key=lambda key: key[0])
dict.items returns tuples of form (key, value) so here you need to specify the sorting key.
I have a list
l=[(1,2),(1,6),(3,4),(3,6),(1,4),(4,3)]
I want to return a list that contains lists by the first number in each tuple.
Something like this:
[[2,4,6],[4,6],[3]]
To make a program that iterates on list and writing a whole function that does it is easy.
I want to find a oneliner - python way of doing it.
Any ideas?
>>> from itertools import groupby
>>> from operator import itemgetter
>>> L = [(1,2), (1,6), (3,4), (3,6), (1,4), (4,3)]
>>> [[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))]
[[2, 4, 6], [4, 6], [3]]
Explanation
This works by using itertools.groupby. groupby finds consecutive groups in an iterable, returning an iterator through key, group pairs.
The argument given to groupby is a key function, itemgetter(0) which is called for each tuple, returning the first item as the key to groupby.
groupby groups elements in their original order so if you want to group by the first number in the list, it must first be sorted so groupby can go through the first numbers in ascending order and actually group them.
>>> sorted(L)
[(1, 2), (1, 4), (1, 6), (3, 4), (3, 6), (4, 3)]
There is the sorted list where you can clearly see the groups that will be created if you look back to the final output. Now you can use groupby to show the key, group pairs.
[(1, <itertools._grouper object at 0x02BB7ED0>), (3, <itertools._grouper object at 0x02BB7CF0>), (4, <itertools._grouper object at 0x02BB7E30>)]
Here are the sorted items grouped by the first number. groupby returns the group for each key as an iterator, this is great and very efficient but for this example we will just convert it to a list to make sure it's working properly.
>>> [(k, list(v)) for k,v in groupby(sorted(L), itemgetter(0))]
[(1, [(1, 2), (1, 4), (1, 6)]), (3, [(3, 4), (3, 6)]), (4, [(4, 3)])]
That is almost the right thing but the required output shows only the 2nd number in the groups in each list. So the following achieves the desired result.
[[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))]
l = [(1, 2), (1, 6), (3, 4), (3, 6), (1, 4), (4, 3)]
d = {}
for (k, v) in l:
d.setdefault(k, []).append(v)
print d.values()
I know it's not a one liner, but perhaps it's easier to read than a one liner.