I have two lists. One list of tuples containing two elements, another containing only strings.
What is the best way to combine these in this way:
list1 = [('1','2'), ('3','4')]
list2 = ['one','two']
expected_result = [('1','2','one'), ('3','4','two')]
I am stuck on something like:
result = [elt+(list2[0],) for elt in list1]
However, I'm not sure if it's possible to iterate 2 lists inside of one list comprehension at the same time. Having a bit of a brain fart here. any help would be appreciated.
Bonus points if it fits on one line (list comprehension style)!
You can zip() the two lists together. This will give you elements like (('1', '2'), 'one'). This assumes the lists are the same length. Then in a list comprehension make a new tuple from those either by concating them, or spreading the first into tuple as below:
list1 = [('1','2'), ('3','4')]
list2 = ['one','two']
[(*t, word) for t, word in zip(list1, list2)]
# [('1', '2', 'one'), ('3', '4', 'two')]
alternatively:
[t + (word,) for t, word in zip(list1, list2)]
List comprehension style solution (one liner)
list1 = [('1','2'), ('3','4')]
list2 = ['one','two']
new_lst = [ list1[i]+(list2[i],) for i in range(len(list1))]
print(new_lst)
>> [('1', '2', 'one'), ('3', '4', 'two')]
Related
I have two lists. I am trying to remove all the elements in the first list occurred prior to any element in the second list. This should be happened only once.
As for an example:
Let,
list1 = ['a','d','k','1','3','a','f','3']
list2=['1','2','3','4','5']
what my resulting list should be:
listResult=['1','3','a','f','3']
in list 1, the element '1' is found in the list2. Hence, all the items prior to '1' has to be removed. This should not be happened with element '3', as the removing process has to be break after one removal.
I have tried with the following but it only considers one given specific element. what i am trying is to not only consider one element and to consider a list of elements.
from itertools import dropwhile
list1 = ['a','d','k','1','3','a','f','3']
element = '1'
list(dropwhile(lambda x: x != element, list1))
The in operator should be used in lambda for containment test:
>>> list(dropwhile(lambda x, s=frozenset(list2): x not in s, list1))
['1', '3', 'a', 'f', '3']
Another interesting but slightly inefficient solution:
>>> from itertools import compress, accumulate
>>> from operator import or_
>>> s = set(list2)
>>> list(compress(list1, accumulate((x in s for x in list1), or_)))
['1', '3', 'a', 'f', '3']
Because the default value of the second parameter of accumulate is equivalent to operator.add, and positive numbers are always regarded as true in Python, the or_ can be omitted:
>>> list(compress(list1, accumulate(x in s for x in list1)))
['1', '3', 'a', 'f', '3']
We can make a set using list1 which can be used to check if item in list2 present in list1.
If it is present, we can take the index of the item and take the subarray from the item index. Then we can break the loop.
list1 = ['a','d','k','1','3','a','f','3']
list2 = ['1','2','3','4','5']
listResult = []
set1 = set(list1)
for i in list2:
if (i in set1):
idx = list1.index(i)
listResult = list1[idx:]
break
print(listResult)
List A:
[('Harry', 'X', 'A'),
('James', 'Y', 'G'),
('John', 'Z', 'D')]
List B:
[('Helen', '2', '(A; B)', '3'),
('Victor', '9', '(C; D; E)', '4'),
('Alan', '10', '(A)', '57'),
('Paul', '11', '(F; B)', '43'),
('Sandra', '12', '(F)', '31')]
Basically I have to compare the third element (for x in listA -> x[2]) from list A and check if is there any list in list B that has the same element (for y in listB, x[2] == y[2]) but I'm just losing my mind with this.
My idea was to get the third element from each list in list B, put them into a new list, and then remove that ";" so I could access each element way more easily.
for x in listB:
j = x[2]
j = j.strip().split(', ')
for k in j:
FinalB.append(k)
FinalB = [(k[1:-1].split(";")) for k in FinalB]
Then I'd take the third element from each list of list A and compare them with the elements inside each list of FinalB: if there was a match, I'd get the index of the element in FinalB (the one that's matched), use that index to access his list in listB and get the first element of his list inside list B (basically, I have to know the names from the users inside each list that have the same 3rd element)
My code so far:
FinalB= []
DomainsList = []
for x in listA:
j = x[2]
j = j.strip().split(', ')
for k in j:
FinalB.append(k)
FinalB = [(k[1:-1].split(";")) for k in FinalB]
for y in listA:
for z in FinalB:
for k in z:
if y[2] == k:
m = FinalB.index(z)
DomainsList.append([listA[m][0],listB[m][0]])
return DomainsList
Yes, this is not working (no error, I probably just did this in an absolute wrong way) and I can't figure out what and where I'm doing wrong.
First, I think a better way to handle '(C; D; E)' is to change it to 'CDE', so the first loop becomes:
FinalB = [filter(str.isalpha, x[2]) for x in listB]
We take each string and keep only the alpha characters, so we end up with:
In [18]: FinalB
Out[18]: ['AB', 'CDE', 'A', 'FB', 'F']
This means we can use listA[x][2] in FinalB[y] to test if we have a match:
for y in listA:
for z in FinalB:
if y[2] in z:
DomainsList.append([y[0], listB[FinalB.index(z)][0]])
I had to tweak the arguments to the append() to pick the right elements, so we end up with:
In [17]: DomainsList
Out[17]: [['Harry', 'Helen'], ['Harry', 'Alan'], ['John', 'Victor']]
Usefully, if instead of '(C; D; E)' you have '(foo; bar; baz)', then with just one tweak the code can work for that too:
import re
FinalB = [filter(None, re.split("[; \(\)]+", x[2])) for x in listB]
The remaining code works as before.
It will always help to start a question with context and details.
The python version could also come into play.
The data structure you have given for us to work with is very questionable - especially the third element in each of the tuples in listB...why have a string element and then define it like this '(C; D; E)' ??
Even though I don't understand where you are coming from with this or what this is meant to achieve,no context provided in post, this code should get you there.
It will give you a list of tupples ( listC ), with each tuple having two elements. Element one having the name from listA and element 2 having the name from listB where they have a match as described in post.
NOTE: at the moment the match is simply done with a find, which will work perfectly with the provided details, however you may need to change this to be suitable for your needs if you could have data that would cause false positives or if you want to ignore case.
listA = [('Harry', 'X', 'A'), ('James', 'Y', 'G'), ('John', 'Z', 'D')]
listB = [('Helen', '2', '(A; B)', '3'),
('Victor', '9', '(C; D; E)', '4'),
('Alan', '10', '(A)', '57'),
('Paul', '11', '(F; B)', '43'),
('Sandra', '12', '(F)', '31')]
listC = []
for a in listA:
for b in listB:
if b[2].find(a[2]) != -1:
listC.append((a[0], b[0]))
print(listC)
This gives you.
[('Harry', 'Helen'), ('Harry', 'Alan'), ('John', 'Victor')]
This question already has answers here:
How can you split a list every x elements and add those x amount of elements to an new list?
(4 answers)
Closed 5 years ago.
I have a list consisting of a repeating patterns i.e.
list=['a','1','first','b','2','second','c','3','third','4','d','fourth']`
I am not sure how long this list will be, it could be fairly long, but I want to create list of the repeating patters i.e. along with populated names
list_1=['a','1','first']
list_2=['b','2','second']
list_3=['c','3','third']
..... etc
What is the best, basic code (not requiring import of modules) that I can use to achieve this?
You can get the chunks using zip():
>>> lst = ['a','1','first','b','2','second','c','3','third','4','d','fourth']
>>> list(zip(*[iter(lst)]*3))
[('a', '1', 'first'), ('b', '2', 'second'), ('c', '3', 'third'), ('4', 'd', 'fourth')]
Using zip() avoids creating intermediate lists, which could be important if you have long lists.
zip(*[iter(lst)]*3) could be rewritten:
i = iter(lst) # Create iterable from list
zip(i, i, i) # zip the iterable 3 times, giving chunks of the original list in 3
But the former, while a little more cryptic, is more general.
If you need names for this lists then I would suggest using a dictionary:
>>> d = {'list_{}'.format(i): e for i, e in enumerate(zip(*[iter(lst)]*3), 1)}
>>> d
{'list_1': ('a', '1', 'first'),
'list_2': ('b', '2', 'second'),
'list_3': ('c', '3', 'third'),
'list_4': ('4', 'd', 'fourth')}
>>> d['list_2']
('b', '2', 'second')
Try this
chunks = [data[x:x+3] for x in xrange(0, len(data), 3)]
It will make sublists with 3 items
Beginner's question.
I have two ordered lists with the same order,
list_1=['de', 'de', 'de', '3']
list_2=['6', '5', '3', 'not']
so the n-th element of list_1 corresponds to the n-th element of list_2.
I want to merge the two lists while perserving their order. Moreover, the list resulting from the merge should consist entirely out of numbers, i.e.
merged_list=['6', '5', '3', '3']
Preferably, I merge by position in the list conditionally on string or numeric values. I have the same issue with other ordered lists, but with those lists I want to replace numeric values with string values. I.a. to solve my troubles with all the ordered lists I have I'd like to do something like:
replace element_n of list_i with element_n of list_j if element_n of list_i equals 'z'
where z is either a numeric value or a string value, dependent on the nature of the list.
You can use zip to aggregates two list items:
>>> list_1 = ['de', 'de', 'de', '3']
>>> list_2 = ['6', '5', '3', 'not']
>>> zip(list_1, list_2)
<zip object at 0x1029e53c8>
>>> list(zip(list_1, list_2))
[('de', '6'), ('de', '5'), ('de', '3'), ('3', 'not')]
, and str.isdigit to check if the given string is a number:
>>> '123'.isdigit()
True
>>> 'de'.isdigit()
False
By combining with conditional expression and list comprehension, you will get what you want:
>>> [a if a.isdigit() else b for a, b in zip(list_1, list_2)]
['6', '5', '3', '3']
I have a list and want to split each elements into a tuple of two elements.
The list looks like:
list_doctors = ['dr.naman_5','dr.akanksha_7','dr.sumant_3']
How do I create a list of the form:
modified_list = [('dr.naman','5'),('dr.akanksha','7'),('dr.sumant','3')]
Try the following.
>>> list_doctors = ['dr.naman_5','dr.akanksha_7','dr.sumant_3']
>>> [tuple(s.split('_')) for s in list_doctors]
[('dr.naman', '5'), ('dr.akanksha', '7'), ('dr.sumant', '3')]
Use split().
>>> list_doctors = ['dr.naman_5','dr.akanksha_7','dr.sumant_3']
>>> modified_list = [item.split('_') for item in list_doctors]
>>> modified_list
[['dr.naman', '5'], ['dr.akanksha', '7'], ['dr.sumant', '3']]