How to generate tuples with some constant values with comprehension? - python

Is it possible to generate tuples with some constant values with comprehension?
I would like to have something like
[
(0, 'A', 'B'),
(1, 'A', 'B'),
(2, 'A', 'B'),
(3, 'A', 'B'),
...
]
so I would take 0, 1, 2, 3, ... from range. But how to get As and Bs, which are not change?

it's not because tuples are immutable that you cannot generate a list of tuples with a variable item only:
result = [(i,'A','B') for i in range(1,5)]
print(result)
yields:
[(1, 'A', 'B'), (2, 'A', 'B'), (3, 'A', 'B'), (4, 'A', 'B')]

Related

Remove all integer from list in python

How do I remove all integers in my list except the last integer?
From
mylist = [('a',1,'b',2,'c',3), ('d',1,'e',2),('f',1,'g',2,'h',3,'i',4)]
To
[('a','b','c',3), ('d','e',2),('f','g','h','i',4)]
I tried doing below but nothing happens.
no_integers = [x for x in mylist if not isinstance(x, int)]
One way using filter with packing:
[(*filter(lambda x: isinstance(x, str), i), j) for *i, j in mylist]
Output:
[('a', 'b', 'c', 3), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
Explanation:
for *i, j in mylist: packs mylist's element (i.e. ('a',1,'b',2,'c',3), ...) into everything until last (*i) and the last (j).
So it will yield (('a',1,'b',2,'c'), 3) and so on.
filter(lambda x: isinstance(x, str), i): from i:('a',1,'b',2,'c'), filters out only str objects.
So ('a',1,'b',2,'c') becomes ('a','b','c').
(*filter, j): unpacks the result of 2 into a tuple whose last element is j.
So it becomes ('a', 'b', 'c', 3).
clear(), pop(), and remove() are methods of list. You can also remove elements from a list with del statements.,In Python, use list methods clear(), pop(), and remove() to remove items (elements) from a list. It is also possible to delete items using del statement by specifying a position or range with an index or slice.,It is also possible to delete all items by specifying the entire range.,See the following example.
l=list(range(10))
print(l)
#[0,1,2,3,4,5,6,7,8,9]
l.clear()
print(l)
#[]
Using only list comprehensions
there will always be the last integer on each tuple. There's no scenario where the end will be a string.
Keeping your above comment in mind,
Your approach is almost right, except for the fact that your list is actually a list of tuples. This means you need a nested loop to iterate through the items inside the sublist.
Knowing that the last element is an integer (last integer) that has to be kept, you can simply just do the above iteration on n-1 items of each sublist, and then append the last item regardless of the condition.
Check comments for an explanation of each component.
[tuple([item for item in sublist if not isinstance(item, int)]+[sublist[-1]]) for sublist in l]
#|___________________________________________________________| |____________|
# | |
# Same as your method, iterating on n-1 items for each tuple |
# append last item
#|____________________________________________________________________________________________|
# |
# Iterate over the list and then iterate over each sublist (tuples) with condition
[('a', 'b', 'c', 3), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
So, simply use your method for iterating inside the sublist, while having a separate for loop to iterate through the sublists.
You can use listcomp and unpacking like this.
[
(*[c for c in subl if not isinstance(c, int)], last)
for *subl, last in mylist
]
Out: [('a', 'b', 'c', 3), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
PS: Updated after this answer. Thanks Chris.
Assumptions
If we can assume the int we want to keep will always be the last element in each tuple, this is very easy. We'll just filter everything except the last element and reconstruct a tuple using the result.
>>> [tuple(list(filter(lambda x: not isinstance(x, int), l[:-1])) + [l[-1]]) for l in mylist]
[('a', 'b', 'c', 3), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
>>>
Less assumption
But what if, as originally specified in your question, we just want to get rid of all ints... except the last one and we don't know what order or positions things will occur in?
First a function that might provide handy:
>>> def partition(pred, lst):
... t, f = [], []
... for x in lst:
... (t if pred(x) else f).append(x)
... return (t, f)
...
>>>
We can easily partition your data into ints and not ints with this:
>>> partition(lambda x: isinstance(x, int), mylist[0])
([1, 2, 3], ['a', 'b', 'c'])
>>> [partition(lambda x: isinstance(x, int), lst) for lst in mylist]
[([1, 2, 3], ['a', 'b', 'c']), ([1, 2], ['d', 'e']), ([1, 2, 3, 4], ['f', 'g', 'h', 'i'])]
>>>
Then we'd just need to discard all but the last of the ints, but how would we know where to put them back together? Well, if we were to enumerate them first...
>>> [partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist]
[([(1, 1), (3, 2), (5, 3)], [(0, 'a'), (2, 'b'), (4, 'c')]), ([(1, 1), (3, 2)], [(0, 'd'), (2, 'e')]), ([(1, 1), (3, 2), (5, 3), (7, 4)], [(0, 'f'), (2, 'g'), (4, 'h'), (6, 'i')])]
>>>
Now we just discard all but the last int, and add it back into the list of not ints to create a single list.
>>> [(i[-1], ni) for i, ni in [partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist]]
[((5, 3), [(0, 'a'), (2, 'b'), (4, 'c')]), ((3, 2), [(0, 'd'), (2, 'e')]), ((7, 4), [(0, 'f'), (2, 'g'), (4, 'h'), (6, 'i')])]
>>> [ni + [i[-1]] for i, ni in [partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist]]
[[(0, 'a'), (2, 'b'), (4, 'c'), (5, 3)], [(0, 'd'), (2, 'e'), (3, 2)], [(0, 'f'), (2, 'g'), (4, 'h'), (6, 'i'), (7, 4)]]
>>>
If we sort by the indexes we added on with enumerate:
>>> [sorted(ni + [i[-1]], key=lambda x: x[0]) for i, ni in [partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist]]
[[(0, 'a'), (2, 'b'), (4, 'c'), (5, 3)], [(0, 'd'), (2, 'e'), (3, 2)], [(0, 'f'), (2, 'g'), (4, 'h'), (6, 'i'), (7, 4)]]
>>>
Now we need to discard the indexes and convert back to tuples.
>>> [tuple(map(lambda x: x[1], sorted(ni + [i[-1]], key=lambda x: x[0]))) for i, ni in [partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist]]
[('a', 'b', 'c', 3), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
>>>
Now, even if we change up the input data, we keep only the last int, and where it originally was:
>>> mylist = [('a',1,'b',2,'c',3,'d',6,'e','f'), ('d',1,'e',2),('f',1,'g',2,'h',3,'i',4)]
>>> [tuple(map(lambda x: x[1], sorted(ni + [i[-1]], key=lambda x: x[0]))) for i, ni in [partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist]]
[('a', 'b', 'c', 'd', 6, 'e', 'f'), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
>>>
The inner list comprehension in the above expression can be replaced by a generator expression and the solution still works.
>>> mylist = [('a',1,'b',2,'c',3,'d',6,'e','f'), ('d',1,'e',2),('f',1,'g',2,'h',3,'i',4)]
>>> [tuple(map(lambda x: x[1], sorted(ni + [i[-1]], key=lambda x: x[0]))) for i, ni in (partition(lambda x: isinstance(x[1], int), enumerate(lst)) for lst in mylist)]
[('a', 'b', 'c', 'd', 6, 'e', 'f'), ('d', 'e', 2), ('f', 'g', 'h', 'i', 4)]
>>>
Use loop and list comprehension
you can iterate over each tuple of list and then using list comprehension remove all the integers and add last element.
mylist = [('a',1,'b',2,'c',3), ('d',1,'e',2),('f',1,'g',2,'h',3,'i',4)]
newlist = []
#print(mylist)
for ele in mylist:
#print(ele)
list_1 = tuple(([ x for x in list(ele) if not str(x).isdigit() ] + [ele[-1]]))
newlist.append(list_1)
print("Final List :")
print(newlist)
after list comprehension add last element with index and convert that list to tuple and append it to your new list.

Convert a list of tuples to a dictionary, based on tuple values

I have a little problem, maybe dumb, but it seems I can't solve it.
I have a list of objects that have members, but let's say my list is this:
l = [(1, 'a'), (2, 'a'), (1, 'b'), (1, 'c'), (3, 'a')]
I want to "gather" all elements based on the value I choose, and to put them into a dictionary based on that value/key (can be both the first or the second value of the tuple).
For example, if I want to gather the values based on the first element, I want something like that:
{1: [(1, 'a'), (1, 'b'), (1, 'c')], 2: [(2, 'a')], 3: [(3, 'a')]}
However, what I achieved until now is this:
>>> {k:v for k,v in zip([e[0] for e in l], l)}
{1: (1, 'c'), 2: (2, 'a'), 3: (3, 'a')}
Can somebody please help me out?
My first thought would be using defaultdict(list) (efficient, in linear time), which does exactly what you were trying to do:
from collections import defaultdict
dic = defaultdict(list)
l = [(1, 'a'), (2, 'a'), (1, 'b'), (1, 'c'), (3, 'a')]
for item in l:
dic[item[0]].append(item)
output
defaultdict(list,{1: [(1, 'a'), (1, 'b'), (1, 'c')], 2: [(2, 'a')], 3: [(3, 'a')]})
Here you go:
l = [(1, 'a'), (2, 'a'), (1, 'b'), (1, 'c'), (3, 'a')]
output_dict = dict()
for item in l:
if item[0] in output_dict:
output_dict[item[0]].append(item)
continue
output_dict[item[0]] = [item]
print(output_dict)
Here with list comprehension, oneliner:
l = [(1, 'a'), (2, 'a'), (1, 'b'), (1, 'c'), (3, 'a')]
print (dict([(x[0], [y for y in l if y[0] == x[0]]) for x in l]))
Output:
{1: [(1, 'a'), (1, 'b'), (1, 'c')], 2: [(2, 'a')], 3: [(3, 'a')]}
First create a dico with list inside :
l = [(1, 'a'), (2, 'a'), (1, 'b'), (1, 'c'), (3, 'a')]
dico={}
for i in range(4):
dico[i]=[]
Then fill this dico
for i in l:
dico[i[0]].append(i)

Create a list including row name, column name and the value from dataframe [duplicate]

This question already has answers here:
Convert pandas dataframe to list of tuples - ('Row', 'Column', Value)
(3 answers)
Closed 2 years ago.
I have the following dataframe:
A B C
A 1 3 0
B 3 2 5
C 0 5 4
All I want is shown below:
my_list = [('A','A',1),('A','B',3),('A','C',0),('B','B',2),('B','C',5),('C','C',4)]
Thanks in advance!
IIUC, you can do:
df.stack().reset_index().agg(tuple,1).tolist()
[('A', 'A', 1),
('A', 'B', 3),
('A', 'C', 0),
('B', 'A', 3),
('B', 'B', 2),
('B', 'C', 5),
('C', 'A', 0),
('C', 'B', 5),
('C', 'C', 4)]
I feel like make the index and value different should be more clear
[*df.stack().iteritems()]
[(('A', 'A'), 1), (('A', 'B'), 3), (('A', 'C'), 0), (('B', 'A'), 3), (('B', 'B'), 2), (('B', 'C'), 5), (('C', 'A'), 0), (('C', 'B'), 5), (('C', 'C'), 4)]
Or
df.reset_index().melt('index').values.tolist()
You can stack and use to_records to obtain a record array from the result:
df.stack().to_frame().to_records().tolist()
# [('A', 'A', 1), ('A', 'B', 3), ('A', 'C', 0), ('B', 'A', 3),...
Hi i think you could done it with splitting the list into parts
with dataframe as data:
for line in data.readlines():
parts = line.split(' ') # split line into parts
part1 = (parts[0])
part2 = (parts[1])
part3 = (parts[2])
Can also use unstack:
In [1638]: df.unstack().to_frame().to_records().tolist()
Out[1638]:
[('A', 'A', 1),
('A', 'B', 3),
('A', 'C', 0),
('B', 'A', 3),
('B', 'B', 2),
('B', 'C', 5),
('C', 'A', 0),
('C', 'B', 5),
('C', 'C', 4)]

Change `itertools.product` iteration order

Given some iterables, itertools.product iterates from back to front, trying all choices of the last iterable before advancing the second-to-last iterable, and trying all choices of the last two iterables before advancing the third-to-last iterable, etc. For instance,
>>> list(itertools.product([2,1,0],['b','c','a']))
[(2, 'b'), (2, 'c'), (2, 'a'), (1, 'b'), (1, 'c'), (1, 'a'), (0, 'b'), (0, 'c'), (0, 'a')]
I would like to iterate over the product in a different manner: the order the tuples should be produced is by the sum of the indices of the elements they contain, i.e., before producing a tuple whose elements' indices in their respective iterables sum to k, produce all tuples whose elements' indices in their respective iterables sum to k-1. For example, after producing the tuple containing the first element (index 0) of every iterable, the next tuples produced should each contain the second element from a single iterable and the first from the rest; after that, the tuples produced should contain the third element from one tuple or the second element from two tuples, etc. Using the above example,
>>> my_product([2,1,0],['b','c','a'])
[(2, 'b'), # element 0 from both iterables
(2, 'c'), (1, 'b'), # elements 0,1 and 1,0 (sums to 1)
(2, 'a'), (1, 'c'), (0, 'b'), # elements 0,2 and 1,1 and 2,0 (sums to 2)
(1, 'a'), (0, 'c'), # elements 1,2 and 2,1 (sums to 3)
(0, 'a')] # elements 2,2 (sums to 4)
Solved this with sorting:
def my_product(*args):
return [tuple(i[1] for i in p) for p in
sorted(itertools.product(*map(enumerate, args)),
key=lambda x: (sum(y[0] for y in x), x))]
Test:
>>> my_product([0,1,2],[3,4,5])
[(0, 3),
(0, 4), (1, 3),
(0, 5), (1, 4), (2, 3),
(1, 5), (2, 4),
(2, 5)]
works also with non-sorted, non-numeric items:
>>> my_product(['s0','b1','k2'],['z3','a4','c5'])
[('s0', 'z3'),
('s0', 'a4'), ('b1', 'z3'),
('s0', 'c5'), ('b1', 'a4'), ('k2', 'z3'),
('b1', 'c5'), ('k2', 'a4'),
('k2', 'c5')]
>>> my_product([2,1,0],['b','c','a'])
[(2, 'b'),
(2, 'c'), (1, 'b'),
(2, 'a'), (1, 'c'), (0, 'b'),
(1, 'a'), (0, 'c'),
(0, 'a')]
and with multiple args:
>>> my_product([2,1,0],['b','c','a'],['x','y','z'])
[(2, 'b', 'x'),
(2, 'b', 'y'), (2, 'c', 'x'), (1, 'b', 'x'),
(2, 'b', 'z'), (2, 'c', 'y'), (2, 'a', 'x'), (1, 'b', 'y'), (1, 'c', 'x'), (0, 'b', 'x'),
(2, 'c', 'z'), (2, 'a', 'y'), (1, 'b', 'z'), (1, 'c', 'y'), (1, 'a', 'x'), (0, 'b', 'y'), (0, 'c', 'x'),
(2, 'a', 'z'), (1, 'c', 'z'), (1, 'a', 'y'), (0, 'b', 'z'), (0, 'c', 'y'), (0, 'a', 'x'),
(1, 'a', 'z'), (0, 'c', 'z'), (0, 'a', 'y'),
(0, 'a', 'z')]
Given that you'll need to check that sum why don' you just use sort:
def my_product(*args):
return list(sorted(itertools.product(*args), key=lambda x: (sum(x), x)))
As an alternative to sorting, this solution makes multiple passes over the result of itertools.product().
Note that it uses the same decorate-manipulate-undecorate pattern that other answers use.
import itertools
# TESTED on Python3
def my_product(*args):
args = [list(enumerate(arg)) for arg in args]
for sum_indexes in range(sum(len(item) for item in args)):
for partial in itertools.product(*args):
indexes, values = zip(*partial)
if sum(indexes) == sum_indexes:
yield values
assert list(my_product([2,1,0],['b','c','a'])) == [
(2, 'b'), # element 0 from both iterables
(2, 'c'), (1, 'b'), # elements 0,1 and 1,0 (sums to 1)
(2, 'a'), (1, 'c'), (0, 'b'), # elements 0,2 and 1,1 and 2,0 (sums to 2)
(1, 'a'), (0, 'c'), # elements 1,2 and 2,1 (sums to 3)
(0, 'a')]

combine list elements

How can I merge/combine two or three elements of a list. For instance, if there are two elements, the list 'l'
l = [(a,b,c,d,e),(1,2,3,4,5)]
is merged into
[(a,1),(b,2),(c,3),(d,4),(e,5)]
however if there are three elements
l = [(a,b,c,d,e),(1,2,3,4,5),(I,II,II,IV,V)]
the list is converted into
[(a,1,I),(b,2,II),(c,3,III),(d,4,Iv),(e,5,V)]
Many thanks in advance.
Use zip:
l = [('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, 5)]
print zip(*l)
Result:
[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

Categories