combine list elements - python

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)]

Related

Use the second value in a list to carry out operation during initial run of a for loop

How do I call a certain value from a dictionary based on the values on a list_a?
list_a = ['S', 'D', 'E']
dict_list = {'S': [('A', 8), ('B', 4), ('D', 6)], 'D': [('C', 5,), ('E', 3)], }
for i in list_a:
print(i)
for I would like to add the value from 'S' to 'D' and then add the value from 'D' to 'E'.
For this example, the answer I am looking for is 9. Basically S to D = 6 and D to E = 3.
Let's use
list_a = ['S', 'D', 'E']
dict_list = {'S': [('A', 8), ('B', 4), ('D', 6)], 'D': [('C', 5), ('E', 3)]}
sum(dict(dict_list[x])[y] for x, y in zip(list_a, list_a[1:]))
# 9
What this does is get pairs of indices, extract the value from the corresponding entries, then sums up the total.
If it is possible for keys not to exist, you may use change dict(dict_list[x])[y] to dict(dict_list.get(x, {}).get(y, 0).

Removing an element from a list based on a condition

I need to remove an element (in this case a tuple) from one list based on a condition (if satisfied) in another list.
I have 2 lists (list of tuples).
List1 = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
List2 = [(1, 2), (1, 3), (1, 2), (2, 3), (2, 2), (3, 2)]
List1 is basically computed from the following code.
import pandas as pd
mapping = {'name': ['a', 'b', 'c', 'd'],'ID': [1,2,3,2]}
df = pd.DataFrame(mapping)
comb = df['name'].to_list()
List1 = list(combinations(comb,2))
# mapping the elements of the list to an 'ID' from the dataframe and creating a list based on the following code
List2 = [(df['ID'].loc[df.name == x].item(), df['ID'].loc[df.name == y].item()) for (x, y) in List1]
Now I need to apply a condition here; looking at List2, I need to look at all tuples in List2 and see if there is any tuple with same 'ID's in it. For example, in List2 I see there is (2,2). So, I want to go back to List1 based on this remove the corresponding tuple which yielded this (2,2) pair.
Essentially my final revised list should be this:
RevisedList = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('c', 'd')]
('b','d') should be removed because they yield (2,2) same IDs in a set
List1 = [('a','b'), ('a','c'), ('a','d'), ('b','c'), ('b','d')]
List2 = [(1,2), (1,3), (1,2), (2,3), (2,2)]
new_List1 = [elem for index,elem in enumerate(List1) if List2[index][0]!=List2[index][1]]
// Result: [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c')]
It is not entirely clear but is this what you are looking for? new_List1 only contains those indexes where at that index List2 has two different numbers in the tuple

How to generate tuples with some constant values with comprehension?

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')]

how can I create word count output in python just by using reduce function?

I have the following list of tuples: [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]
I would like to know if I can utilize python's reduce function to aggregate them and produce the following output : [('a', 3), ('b', 1), ('c', 2)]
Or if there are other ways, I would like to know as well (loop is fine)
It seems difficult to achieve using reduce, because if both tuples that you "reduce" don't bear the same letter, you cannot compute the result. How to reduce ('a',1) and ('b',1) to some viable result?
Best I could do was l = functools.reduce(lambda x,y : (x[0],x[1]+y[1]) if x[0]==y[0] else x+y,sorted(l))
it got me ('a', 3, 'b', 1, 'c', 1, 'c', 1). So it kind of worked for the first element, but would need more than one pass to do the other ones (recreating tuples and make another similar reduce, well, not very efficient to say the least!).
Anyway, here are 2 working ways of doing it
First, using collections.Counter counting elements of the same kind:
l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]
import collections
c = collections.Counter()
for a,i in l:
c[a] += i
We cannot use listcomp because each element has a weight (even if here it is 1)
Result: a dictionary: Counter({'a': 3, 'c': 2, 'b': 1})
Second option: use itertools.groupby on the sorted list, grouping by name/letter, and performing the sum on the integers bearing the same letter:
print ([(k,sum(e for _,e in v)) for k,v in itertools.groupby(sorted(l),key=lambda x : x[0])])
result:
[('a', 3), ('b', 1), ('c', 2)]
The alternative approach using defaultdict subclass and sum function:
import collections
l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]
d = collections.defaultdict(list)
for t in l:
d[t[0]].append(t[1])
result = [(k,sum(v)) for k,v in d.items()]
print(result)
The output:
[('b', 1), ('a', 3), ('c', 2)]
Another way is that to create your custom reduce function.
for example:
l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]
def myreduce(func , seq):
output_dict = {}
for k,v in seq:
output_dict[k] = func(output_dict.get(k,0),v)
return output_dict
myreduce((lambda sum,value:total+sum),l)
output:
{'a': 3, 'b': 1, 'c': 2}
later on you can modify the generated output as a list of tuples.

Check list of tuples where first element of tuple is specified by defined string

This question is similar to Check that list of tuples has tuple with 1st element as defined string but no one has properly answered the "wildcard" question.
Say I have [('A', 2), ('A', 1), ('B', 0.2)]
And I want to identify the tuples where the FIRST element is A. How do I return just the following?
[('A', 2), ('A', 1)]
Using a list comprehension:
>>> l = [('A', 2), ('A', 1), ('B', 0.2)]
>>> print([el for el in l if el[0] == 'A'])
[('A', 2), ('A', 1)]
You could use Python's filter function for this as follows:
l = [('A', 2), ('A', 1), ('B', 0.2)]
print filter(lambda x: x[0] == 'A', l)
Giving:
[('A', 2), ('A', 1)]
Simple enough list comprehension:
>>> L = [('A', 2), ('A', 1), ('B', 0.2)]
>>> [(x,y) for (x,y) in L if x == 'A']
[('A', 2), ('A', 1)]

Categories