I have the following list in Python:
[('1','2','3'),('5','6','7')]
I need to convert the tuples inside the list into integer([(1,2,3),(5,6,7)]) in a functional way.
I can do them for a list using this simple code: map(lambda x:int(x),['1','2','3'])
But how shall i apply the same concept for list of tuples ?
(I know the imperative way of doing this.)
tl = [('1','2','3'),('5','6','7')]
[tuple(int(x) for x in t) for t in tl]
# [(1, 2, 3), (5, 6, 7)]
If you really want the map syntax,
map(lambda t:tuple(map(int, t)), tl)
# [(1, 2, 3), (5, 6, 7)]
How about the following:
[tuple([int(str_int) for str_int in tup]) for tup in list_of_string_tuples]
This hybrid works:
>>> [tuple(map(int,t)) for t in [('1','2','3'),('5','6','7')]]
[(1, 2, 3), (5, 6, 7)]
Related
I'm committing a crime in python on purpose. This is a bad way of doing this.
The GOAL here is cursed code. All on one line.
I have basically whats below
with open("file") as f:
[int(x) for x in [y for y in f.read().split()]
I cannot use
with open("file") as f:
a = f.read().split()
[x for x in [(a[i-1, e]) for i, e in enumerate(a) if i > 0] ...]
because the goal is to have this in one line (aside from the with open)
I would like to return from the original object the current element and either the previous one or the next one.
To illustrate it clearly.
a = [1, 2, 3, 4, 5]
After the illegal code would return
[(1, 2), (2, 3), (3, 4), (4, 5), (5, ?)]
So again the focus here is not production code. This is purely to see how much we can abuse the language.
So far I've found https://code.activestate.com/recipes/204297/ which references the use of local in python2, after mucking around with it I found that the interface for it is a little different.
I've been able to get the object in memory but I dont know how to actually use this object now that I have it.
local()['.0']
Most attributes seem to be missing, no __self__ to call.
Please share your most cursed ideas for this.
Normally, I would use tee and islice on the generator for something like this:
from itertools import tee, islice
with open("file") as f:
a, b = tee(f.read().split())
b = islice(b, 1, None)
list(zip(a, b))
You can convert this into a one-liner using (abusing) the walrus operator (:=):
list(zip((k := tee(f.read().split()))[0], islice(k[1], 1, None)))
The result is
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
If you want the last element to be padded, use zip_longest instead of zip:
from itertools import tee, islice, zip_longest
...
list(zip_longest((k := tee(f.read().split()))[0], islice(k[1], 1, None), fillvalue='?'))
The result in this case is
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, '?')]
The nice thing about using iterators rather than lists this way is that while f.read().split() is a sequence of known length, the tee and islice will work on any iterable, even if the length is unknown.
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.
Is there a python builtin that does the same as tupler for a set of lists, or something similar:
def tupler(arg1, *args):
length = min([len(arg1)]+[len(x) for x in args])
out = []
for i in range(length):
out.append(tuple([x[i] for x in [arg1]+args]))
return out
so, for example:
tupler([1,2,3,4],[5,6,7])
returns:
[(1,5),(2,6),(3,7)]
or perhaps there is proper pythony way of doing this, or is there a generator similar???
I think you're looking for zip():
>>> zip([1,2,3,4],[5,6,7])
[(1, 5), (2, 6), (3, 7)]
have a look at the built-in zip function http://docs.python.org/library/functions.html#zip
it can also handle more than two lists, say n, and then creates n-tuples.
>>> zip([1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14])
[(1, 5, 9, 13), (2, 6, 10, 14)]
zip([1,2,3,4],[5,6,7])
--->[(1,5),(2,6),(3,7)]
args = [(1,5),(2,6),(3,7)]
zip(*args)
--->[1,2,3],[5,6,7]
The proper way is to use the zip function.
Alternativerly we can use list comprehensions and the built-in enumerate function
to achieve the same result.
>>> L1 = [1,2,3,4]
>>> L2 = [5,6,7]
>>> [(value, L2[i]) for i, value in enumerate(L1) if i < len(L2)]
[(1, 5), (2, 6), (3, 7)]
>>>
The drawback in the above example is that we don't always iterate over the list with the minimum length.
can we remove a entry from the sets.
what are the commands to use for it?
like, my set conatins (6,5) , (6,7), (7,9)...I need to remove the second entry...what shud I do??
my_set.remove((6, 7))
The remove() method can be used to remove items from a set.
You can use remove():
>>> s = set([1, 2, 3])
>>> s.remove(2)
>>> s
set([1, 3])
a -= set([(6, 7)])
:-)
If you've got a list of those tuples you can clear it out like this:
l = [(1,2),(3,4),(5,6)]
[(1, 2), (3, 4), (5, 6)]
l.remove((3,4))
[(1, 2), (5, 6)]
I have a list of lists of tuples
A= [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]
The outer list can have any number of inner lists, the inner lists can have any number of tuples, a tuple always has 3 integers.
I want to generate all combination of tuples, one from each list:
[(1,2,3),(7,8,9),(2,1,0)]
[(1,2,3),(7,8,9),(1,3,5)]
[(1,2,3),(8,7,6),(2,1,0)]
...
[(4,5,6),(5,4,3),(1,3,5)]
A simple way to do it is to use a function similar to itertools.poduct()
but it must be called like this
itertools.product([(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)])
i.e the outer list is removed. And I don't know how to do that. Is there a better way to generate all combinations of tuples?
itertools.product(*A)
For more details check the python tutorial
This works for your example, if there is only one level of nested lists (no lists of lists of lists):
itertools.product(*A)
you can probably call itertools.product like so:
itertools.product(*A) # where A is your list of lists of tuples
This way it expands your list's elements into arguments for the function you are calling.
Late to the party but ...
I'm new to python and come from a lisp background. This is what I came up with (check out the var names for lulz):
def flatten(lst):
if lst:
car,*cdr=lst
if isinstance(car,(list)):
if cdr: return flatten(car) + flatten(cdr)
return flatten(car)
if cdr: return [car] + flatten(cdr)
return [car]
Seems to work. Test:
A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]
flatten(A)
Result:
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]
Note: the line car,*cdr=lst only works in Python 3.0
This is not exactly one step, but this would do what you want if for some reason you don't want to use the itertools solution:
def crossprod(listoflists):
if len(listoflists) == 1:
return listoflists
else:
result = []
remaining_product = prod(listoflists[1:])
for outertupe in listoflists[0]:
for innercombo in remaining_product[0]:
newcombo = [outertupe]
newcombo.append(innercombo)
result.append(newcombo)
return result
def flatten(A)
answer = []
for i in A:
if type(i) == list:
ans.extend(i)
else:
ans.append(i)
return ans
This may also be achieved using list comprehension.
In [62]: A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]
In [63]: improved_list = [num for elem in A for num in elem]
In [64]: improved_list
Out[64]: [(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]