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)
Related
I'm trying to remove the odd-indexed elements from my list (where zero is considered even) but removing them this way won't work because it throws off the index values.
lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
def remove_odd_elements(lst):
i=0
for element in lst:
if i % 2 == 0:
pass
else:
lst.remove(element)
i = i + 1
How can I iterate over my list and cleanly remove those odd-indexed elements?
You can delete all odd items in one go using a slice:
del lst[1::2]
Demo:
>>> lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
>>> del lst[1::2]
>>> lst
['712490959', '623726061', '552157404', '1285252944', '1130181076', '552157404', '545600725']
You cannot delete elements from a list while you iterate over it, because the list iterator doesn't adjust as you delete items. See Loop "Forgets" to Remove Some Items what happens when you try.
An alternative would be to build a new list object to replace the old, using a list comprehension with enumerate() providing the indices:
lst = [v for i, v in enumerate(lst) if i % 2 == 0]
This keeps the even elements, rather than remove the odd elements.
Since you want to eliminate odd items and keep the even ones , you can use a filter as follows :
>>>filtered_lst=list(filter(lambda x : x % 2 ==0 , lst))
this approach has the overhead of creating a new list.
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')]
How do you access the last index of each list of list?
list = [['hey', 'who', '09'], ['lol', 'ae', '12'], ['e', 's', '1']]
^ ^ ^
By using a list comprehension and indexing with [-1]
lst = [['hey', 'who', '09'], ['lol', 'ae', '12'], ['e', 's', '1']]
new_lst = [x[-1] for x in lst]
Side note: you shouldn't name your list list.
You can do this this way -
for l in list:
# Here l is the element of list
# As l is also a list, the you can access last element
# of l using negative indexing
print l[-1]
If you want to create another list using those you can do -
new = [l[-1] for l in list]
Above code assumes that every element of list is also a non-empty list. If it may happen that they can be other than list, you may want to check if it is indeed a list. Check also for empty lists.
Also you may want to avoid using list as variable name
I've no issue with the other answers, except both the title and text asked:
How do you access the last index of each list of list?
The other answers showed how to access the last element of each list of list.
To access the last index of each list of list, try:
>>> my_list = [['hey', 'who', '09'], ['lol', 'ae'], ['e']]
>>> my_indicies = [len(sub_list) - 1 for sub_list in my_list]
>>> my_indicies
[2, 1, 0]
Returns -1 as the last index if the sublist is empty and can't be indexed.
I am looking for some help comparing the order of 2 Python lists, list1 and list2, to detect when list2 is out of order.
list1 is static and contains the strings a,b,c,d,e,f,g,h,i,j. This is the "correct" order.
list2 contains the same strings, but the order and the number of strings may change. (e.g. a,b,f,d,e,g,c,h,i,j or a,b,c,d,e)
I am looking for an efficient way to detect when list2 is our of order by comparing it against list1.
For example, if list2 is a,c,d,e,g,i should return true (as the strings are in order)
While, if list2 is a,d,b,c,e should return false (as string d appears out of order)
First, let's define list1:
>>> list1='a,b,c,d,e,f,g,h,i,j'.split(',')
>>> list1
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
While your list1 happens to be in alphabetical order, we will not assume that. This code works regardless.
Now, let's create a list2 that is out-of-order:
>>> list2 = 'a,b,f,d,e,g,c,h,i,j'.split(',')
>>> list2
['a', 'b', 'f', 'd', 'e', 'g', 'c', 'h', 'i', 'j']
Here is how to test whether list2 is out of order or not:
>>> list2 == sorted(list2, key=lambda c: list1.index(c))
False
False means out-of-order.
Here is an example that is in order:
>>> list2 = 'a,b,d,e'.split(',')
>>> list2 == sorted(list2, key=lambda c: list1.index(c))
True
True means in-order.
Ignoring elements of list1 not in list2
Let's consider a list2 that has an element not in list1:
>>> list2 = 'a,b,d,d,e,z'.split(',')
To ignore the unwanted element, let's create list2b:
>>> list2b = [c for c in list2 if c in list1]
We can then test as before:
>>> list2b == sorted(list2b, key=lambda c: list1.index(c))
True
Alternative not using sorted
>>> list2b = ['a', 'b', 'd', 'd', 'e']
>>> indices = [list1.index(c) for c in list2b]
>>> all(c <= indices[i+1] for i, c in enumerate(indices[:-1]))
True
Why do you need to compare it to list1 since it seems like list1 is in alphabetical order? Can't you do the following?
def is_sorted(alist):
return alist == sorted(alist)
print is_sorted(['a','c','d','e','g','i'])
# True
print is_sorted(['a','d','b','c','e'])
# False
Here's a solution that runs in expected linear time. That isn't too important if list1 is always 10 elements and list2 isn't any longer, but with longer lists, solutions based on index will experience extreme slowdowns.
First, we preprocess list1 so we can quickly find the index of any element. (If we have multiple list2s, we can do this once and then use the preprocessed output to quickly determine whether multiple list2s are sorted):
list1_indices = {item: i for i, item in enumerate(list1)}
Then, we check whether each element of list2 has a lower index in list1 than the next element of list2:
is_sorted = all(list1_indices[x] < list1_indices[y] for x, y in zip(list2, list2[1:]))
We can do better with itertools.izip and itertools.islice to avoid materializing the whole zip list, letting us save a substantial amount of work if we detect that list2 is out of order early in the list:
# On Python 3, we can just use zip. islice is still needed, though.
from itertools import izip, islice
is_sorted = all(list1_indices[x] < list1_indices[y]
for x, y in izip(list2, islice(list2, 1, None)))
is_sorted = not any(list1.index(list2[i]) > list1.index(list2[i+1]) for i in range(len(list2)-1))
The function any returns true if any of the items in an iterable are true. I combined this with a generator expression that loops through all the values of list2 and makes sure they're in order according to list1.
if list2 == sorted(list2,key=lambda element:list1.index(element)):
print('sorted')
Let's assume that when you are writing that list1 is strings a,b,c,d,e,f,g,h,i that this means that a could be 'zebra' and string b could actually be 'elephant' so the order may not be alphabetical. Also, this approach will return false if an item is in list2 but not in list1.
good_list2 = ['a','c','d','e','g','i']
bad_list2 = ['a','d','b','c','e']
def verify(somelist):
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
while len(list1) > 0:
try:
list1 = list1[:list1.index(somelist.pop())]
except ValueError:
return False
return True
I have two list:
a=['1','2','3','3','3']
b=['a','b','c','d','e']
these two lists have the same amount of items. I want to delete duplicate in a and for b with same index. for this example, I would like to have the result as
a=['1','2','3']
b=['a','b','c']
I am not so familiar with Python, the only way I think is to use loop
for item in a
if find duplicate
delete b with same index
I want to ask, is there any better way to do this, other than using loop?
You can use a set for this:
>>> seen = set()
>>> new_a, new_b = [], []
>>> for x, y in zip(a, b):
... if x not in seen:
... new_a.append(x)
... new_b.append(y)
... seen.add(x)
...
>>> new_a
['1', '2', '3']
>>> new_b
['a', 'b', 'c']
Another way to do it using itertools.compress(Python 2.7+ and 3.1+ only):
>>> from itertools import compress, tee
>>> seen = set()
>>> f1, f2 = tee(True if x not in seen and not seen.add(x) else False for x in a)
>>> list(compress(a, f1))
['1', '2', '3']
>>> list(compress(b, f2))
['a', 'b', 'c']
You can use set for removing duplicate entries in a list. Please use following code to get desired output.
#!/usr/bin/python
a=['1','2','3','3','3']
b=['a','b','c','d','e']
a=set(a)
print list(a)
lena=len(a)
b=set(b)
b=list(b)
print b[:lena]
output:
>>>
['1', '3', '2']
['a', 'c', 'b']