I have the following data structure in Python 3:
foo = [(1, 'ADTABC', 7), (3, 'ACHDAT', 8), (1, 'AQNDXB', 15), (2, 'AFTCBA', 14)]
The first and second elements of each tuple are guaranteed to be unique together. I want to create a dictionary that has as the key the concatenation of the first and second elements and as the value the third element:
{'1ADTABC': 7, '3ACHDAT': 8, '1AQNDXB': 15, '2AFTCBA': 14}
How do I achieve this?
Why? The collection you see is the result of a SqlAlchemy query. The third field is the unique id in the database. I need to quickly and efficiently retrieve the Id given the other two elements. Since these values do not really get updated, there is no need to make roundtrips to the db for the retrieval.
You can do that without string concat like:
Code:
foo_dict = {x[0:2]: x[2] for x in foo}
String concat is not the best way to go about this since it requires the creation of yet a another object, but does actual create any extra information. A tuple will use the original objects, but still achieve the need to key a dict.
Test Code:
foo = [(1, 'ADTABC', 7), (3, 'ACHDAT', 8), (1, 'AQNDXB', 15), (2, 'AFTCBA', 14)]
foo_dict = {x[0:2]: x[2] for x in foo}
print(foo)
print(foo_dict)
Results:
[(1, 'ADTABC', 7), (3, 'ACHDAT', 8), (1, 'AQNDXB', 15), (2, 'AFTCBA', 14)]
{(1, 'ADTABC'): 7, (3, 'ACHDAT'): 8, (1, 'AQNDXB'): 15, (2, 'AFTCBA'): 14}
h = {str(a) + b: c for a,b,c in foo}
Related
Is there any standard library Python or Numpy operation for doing the following:
my_array = [(1, 3), (3, 4), (4, 5), (5, 7), (10, 12), (12, 17), (21, 24)]
new_array = magic_function(my_array)
print(new_array)
> [(1, 7), (10, 17), (21, 24)]
I feel like something in itertools should be able to do this, seems like something a lot of people would use. We can assume the list is sorted by onset times already. It wouldn't be hard to do that anyway, you'd just use the sorted function with a key on the first element.
Apologies if this question has already been asked, wasn't sure how to word this problem, but this could be seen as a list of onsets and offsets and I want to merge elements with adjacent/equivalent timing.
EDIT: Inspired by #chris-charley's answer below, which relies on some third party module, I just wrote up a small function which does what I wanted.
import re
def magic_function(mylist):
# convert list to intspan
intspan = ','.join([f'{int(a)}-{int(b)}' for (a,b) in mylist])
# collapse adjacent ranges
intspan = re.sub(r'\-(\d+)\,\1', '', intspan)
# convert back to list
return [tuple(map(int, _.split('-'))) for _ in intspan.split(',')]
Here is the same function generalized for floats also:
import re
def magic_function(mylist):
# convert list to floatspan
floatspan = ','.join([f'{float(a)}-{float(b)}' for (a,b) in mylist])
# collapse adjacent ranges
floatspan = re.sub(r'\-(\d+\.?\d+?)+\,\1', '', floatspan)
# convert back to list
return [tuple(map(float, _.split('-'))) for _ in floatspan.split(',')]
intspan has the methods from_ranges() and ranges() to produce the results you need.
>>> from intspan import intspan
>>> my_array = [(1, 3), (3, 4), (4, 5), (5, 7), (10, 12), (12, 17), (21, 24)]
>>> intspan.from_ranges(my_array).ranges()
[(1, 7), (10, 17), (21, 24)]
I am a newbie to python. Trying to learn how to access Lists inside a Tuple inside a List. My List is:
holidays = [(0,),
(1, [2, 16]),
(2, [20]),
(4, [14]),
(5, [29]),
(7, [4]),
(9, [4]),
(11, [23, 24]),
(12, [25])]
I would like to know the best way to access each tuple and its list in a more efficient way. I tried using:
for i, tuples in enumerate(holidays):
for list in tuples:
print list
But i get the following error:
for list in tuples:
TypeError: 'int' object is not iterable
Help would be much appreciated.
You need to remove the i in the first for loop:
for tuples in enumerate(holidays):
for list in tuples:
print list
short version
[y for x in holidays if isinstance(x, tuple) for y in x if isinstance(y, list)]
You can't do a for .. in LOOP on an integer, that's why the program cras
Well, your holidays list is not uniform: the first entry is an integer (0), the others are tuples.
holidays = [0, # <- integer
(1, [2, 16]),
(2, [20]),
(4, [14]),
(5, [29]),
(7, [4]),
(9, [4]),
(11, [23, 24]),
(12, [25])]
Here is a possible loop:
for entry in holidays:
if entry == 0:
continue # don't know what to do with zero
month, days = entry
print(month, days)
We use unpaking to extract the month and the days.
See Tuples and Sequences in the Python tutorial.
Change your first element 0 to (0), Also, remove 'i' from your for loop, as told by Stavros, it will work.
holidays = [([0]),
(1, [2, 16]),
(2, [20]),
(4, [14]),
(5, [29]),
(7, [4]),
(9, [4]),
(11, [23, 24]),
(12, [25])]
tuples in enumerate(holidays):
list in tuples:
print list
Let's say I have a list like so: [(1, (1,2)), (2, (23, -10)), (3, (4, 5))...]
I want to get (1,2), (23, -10), etc
edit: Thanks for help. I didn't know about list comprehension as I'm not too familiar with python
Try Something like this:-
Here is List and get other list of tuples:-
a = [(1, (1,2)), (2, (23, -10)), (3, (4, 5))...]
b = map(lambda item: item[1], a)
print b
This will solve your problem.
Here is list of tuples where second elem of each tuple is also a tuple. To get that second elem we are going to use lambda that is going to take elements from list and just return second item from that element, in this case being desired tuple. The map function also creates a list of returned values.
>>> list_of_nested_tuples = [(1, (1, 2)), (2, (23, -10)), (3, (4, 5))]
>>> b = map(lambda item: item[1], list_of_nested_tuples)
>>> b
[(1, 2), (23, -10), (4, 5)]
Take note that it would be more clear to just use list comprehension like so
>>> [elem[1] for elem in list_of_nested_tuples]
[(1, 2), (23, -10), (4, 5)]
Yes, you can iterate over all tuples and then take the second element:
list = [(1, (1,2)), (2, (23, -10)), (3, (4, 5))]
for elem in list:
print(elem[1])
In each iteration elem value its (1,(1,2)) -> (2,(23,-10)) -> ....
Then you take the second item of the tuple (index 1)
I have created a program using python Dictionary. In this simple program i can not understand the memory structure of the dictionary. And when I retrieve the data from the dictionary at that time the data is not retrieve in the sequence.
Digit = {1 : One, 2: Two,3: Three,4: Four,5: Five,6: Six,7: Seven,8: Eight,9: nine,0: Zero}
print Digit
It will give me the output like thatTwo,Three,Five,Four etc. If I want it ordered in sequence what do I have to do ?
Dictionaries are arbitrarily ordered in Python. The order is not guaranteed and you should not rely on it. If you need an ordered collection, use either OrderedDict or a list.
If you want to access the dictionary in key order, first get a list of the keys then sort it and then step through that:
keys = Digit.keys()
keys.sort()
for i in keys:
print Digit[i]
If you absolutely want to store ordered data, you could use OrderedDict as Burhan Khalid suggested in his answer:
>>> from collections import OrderedDict
>>> Digit = [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four"), (5, "Five"), (6, "Six"), (7, "Seven"), (8, "Eight"), (9, "Nine"), (0, "Zero")]
>>> Digit = OrderedDict(Digit)
>>> Digit
OrderedDict([(1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four'), (5, 'Five'), (6, 'Six'), (7, 'Seven'), (8, 'Eight'), (9, 'Nine'), (0, 'Zero')])
>>> for k,v in Digit.items():
... print k, v
...
1 One
2 Two
3 Three
4 Four
5 Five
6 Six
7 Seven
8 Eight
9 Nine
0 Zero
Let's say I have the following two lists of tuples
myList = [(1, 7), (3, 3), (5, 9)]
otherList = [(2, 4), (3, 5), (5, 2), (7, 8)]
returns => [(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)]
I would like to design a merge operation that merges these two lists by checking for any intersections on the first element of the tuple, if there are intersections, add the second elements of each tuple in question (merge the two). After the operation I would like to sort based upon the first element.
I am also posting this because I think its a pretty common problem that has an obvious solution, but I feel that there could be very pythonic solutions to this question ;)
Use a dictionary for the result:
result = {}
for k, v in my_list + other_list:
result[k] = result.get(k, 0) + v
If you want a list of tuples, you can get it via result.items(). The resulting list will be in arbitrary order, but of course you can sort it if desired.
(Note that I renamed your lists to conform with Python's style conventions.)
Use defaultdict:
from collections import defaultdict
results_dict = defaultdict(int)
results_dict.update(my_list)
for a, b in other_list:
results_dict[a] += b
results = sorted(results_dict.items())
Note: When sorting sequences, sorted sorts by the first item in the sequence. If the first elements are the same, then it compares the second element. You can give sorted a function to sort by, using the key keyword argument:
results = sorted(results_dict.items(), key=lambda x: x[1]) #sort by the 2nd item
or
results = sorted(results_dict.items(), key=lambda x: abs(x[0])) #sort by absolute value
A method using itertools:
>>> myList = [(1, 7), (3, 3), (5, 9)]
>>> otherList = [(2, 4), (3, 5), (5, 2), (7, 8)]
>>> import itertools
>>> merged = []
>>> for k, g in itertools.groupby(sorted(myList + otherList), lambda e: e[0]):
... merged.append((k, sum(e[1] for e in g)))
...
>>> merged
[(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)]
This first concatenates the two lists together and sorts it. itertools.groupby returns the elements of the merged list, grouped by the first element of the tuple, so it just sums them up and places it into the merged list.
>>> [(k, sum(v for x,v in myList + otherList if k == x)) for k in dict(myList + otherList).keys()]
[(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)]
>>>
tested for both Python2.7 and 3.2
dict(myList + otherList).keys() returns an iterable containing a set of the keys for the joined lists
sum(...) takes 'k' to loop again through the joined list and add up tuple items 'v' where k == x
... but the extra looping adds processing overhead. Using an explicit dictionary as proposed by Sven Marnach avoids it.