I have a list of lists of strings, like this:
l = [['apple','banana','kiwi'],['chair','table','spoon']]
Given a string, I want its index in l. Experimenting with numpy, this is what I ended up with:
import numpy as np
l = [['apple','banana','kiwi'],['chair','table','spoon']]
def ind(s):
i = [i for i in range(len(l)) if np.argwhere(np.array(l[i]) == s)][0]
j = np.argwhere(np.array(l[i]) == s)[0][0]
return i, j
s = ['apple','banana','kiwi','chair','table','spoon']
for val in s:
try:
print val, ind(val)
except IndexError:
print 'oops'
This fails for apple and chair, getting an indexerror. Also, this just looks bad to me. Is there some better approch to doing this?
Returns a list of tuples containing (outer list index, inner list index), designed such that the item you're looking for can be in multiple inner lists:
l = [['apple','banana','kiwi'],['chair','table','spoon']]
def findItem(theList, item):
return [(ind, theList[ind].index(item)) for ind in xrange(len(theList)) if item in theList[ind]]
findItem(l, 'apple') # [(0, 0)]
findItem(l, 'spoon') # [(1, 2)]
If you want to use numpy, you don't need to roll your own:
import numpy as np
l = np.array([['apple','banana','kiwi'],['chair','table','spoon']])
s = ['apple','banana','kiwi','chair','table','spoon']
for a in s:
arg = np.argwhere(l==a)
print a, arg, tuple(arg[0]) if len(arg) else None
l = [['apple','banana','kiwi'],['chair','table','spoon']]
def search(lst, item):
for i in range(len(lst)):
part = lst[i]
for j in range(len(part)):
if part[j] == item: return (i, j)
return None
I'd create a dictionary to map the items to their indices:
>>> import numpy as np
>>> l = [['apple','banana','kiwi'],['chair','table','spoon']]
>>> a = np.array(l,dtype=object)
>>> a
array([[apple, banana, kiwi],
[chair, table, spoon]], dtype=object)
>>> d = {s:idx for (idx),s in np.ndenumerate(a)}
>>> d['apple']
(0, 0)
>>> d['chair']
(1, 0)
numpy + ndenumerate is nice for creating the index, but it's definitely not necessary. Of course, this is going to be most efficient if you can create the index once and then reuse it for subsequent searches.
One way is to make use of enumerate:
l = [['apple','banana','kiwi'],['chair','table','spoon']]
s = ['apple','banana','kiwi','chair','table','spoon']
for a in s:
for i, ll in enumerate(l):
for j, b in enumerate(ll):
if a == b:
print a, i, j
In your line that computes i, you already have the answer if you apply argwhere to the entire list, rather than each sublist. There is no need to search again for j.
def ind(s):
match = np.argwhere(np.array(l == s))
if match:
i, j = match[0]
else:
return -1, -1
This is will return the indeces of the first occurence of the string you're searching for.
Also, you might consider how this method is impacted as the complexity of the problem increases. This method will iterate over every element of your list, so the runtime cost increases as the list becomes bigger. So, if the number of test strings you're trying to find in the list also increases, you might want to think about using a dictionary to create a lookup table once, then subsequent searches for test strings are cheaper.
def make_lookup(search_list):
lookup_table = {}
for i, sublist in enumerate(list):
for j, word in enumerate(sublist):
lookup_table[word] = (i, j)
return lookup_table
lookup_table = make_lookup(l)
def ind(s):
if s in lookup_table:
return lookup_table[s]
else:
return -1, -1
To get index of list of list in python:
theList = [[1,2,3], [4,5,6], [7,8,9]]
for i in range(len(theList)):
if 5 in theList(i):
print("[{0}][{1}]".format(i, theList[i].index(5))) #[1][1]
This solution will find all occurrences of the string you're searching for:
l = [['apple','banana','kiwi','apple'],['chair','table','spoon']]
def findItem(theList, item):
return [(i, j) for i, line in enumerate(theList)
for j, char in enumerate(line) if char == item]
findItem(l, 'apple') # [(0, 0), (0, 3)]
findItem(l, 'spoon') # [(1, 2)]
Related
Find all distinct permutations of a string where only certain indices are allowed to be permuted.
e.g string_perms('test_world', [2,3]) --> ['test_world', 'tets_world']
I have an answer but it looks very dirty. Is there a more elegant way to do it?
from itertools import permutations
def string_perms(s, indices):
final = []
target = [let for ind,let in enumerate(s) if ind in indices]
perms = list(set(permutations(target)))
temp = list(s)
for perm in perms:
for ind,let in enumerate(perm):
temp[indices[ind]] = let
final.append(''.join(temp))
return final
You can use an iterator with a list comprehension:
import itertools as it
def string_perms(s, indices):
for _i in it.permutations([s[j] for j in indices], len(indices)):
i = iter(_i)
yield ''.join(a if j not in indices else next(i) for j, a in enumerate(s))
print(list(string_perms('test_world', [2,3])))
Output:
['test_world', 'tets_world']
A variant, playing with numpy direct indexing.
import numpy as np
def string_perms(s, indices):
r = np.arange(len(s), dtype=int)
for p in list(permutations(indices)):
r[np.array(indices, dtype=int)] = p
yield ''.join(np.array(list(s))[r])
print(list(string_perms('test_world', [2,3])))
print(list(string_perms("azerty", [2,4,5])))
Output:
['test_world', 'tets_world']
['azerty', 'azeryt', 'aztrey', 'aztrye', 'azyret', 'azyrte']
I have a list that looks like this:
lst = [['Apple Pie', 'Carrot Cake'], ['Steak', 'Chicken']]
I would like to find the index of the list that contains the word ' Carrot', so in this case, the output should be 0
I have tried to make a function
def find_index(l, c):
for i, v in enumerate(l):
if c in v:
return i
res = find_index(lst, 'Carrot')
but this does not work since it looks for items in the list.
Can anyone help me to retreive the index of the list that contains 'Carrot'?
Thanks!
Edit:
I received multiple answers for this question, and they all worked. so I decided to time them and accept the fastest one as the answer. here are the results:
import timeit
lst = [['Apple Pie', 'Carrot Cake'], ['Steak', 'Chicken']]
def find_index(l,c):
for i,v in enumerate(l):
for j in v:
if c in j:
return i
print(timeit.timeit('%s'%(find_index(lst,'Carrot Cake'))))
def find_index(l, c):
for i, v in enumerate(l):
if any(c in x for x in v):
return i
print(timeit.timeit('%s'%(find_index(lst,'Carrot Cake'))))
def function(list_contains,word_to_know):
for x in list_contains:
for y in x:
if word_to_know in y:
return list_contains.index(x)
print(timeit.timeit('%s'%(function(lst,'Carrot Cake'))))
def index_of_substr(l, substr):
for i, inner_list in enumerate(l):
for text in inner_list:
if substr in text:
return i
return -1
print(timeit.timeit('%s'%(function(lst,'Carrot Cake'))))
0.005458000000000001
0.005462599999999998
0.005485600000000004
0.0054621000000000045
use this function it will print the index
lst = [['Apple Pie', 'Carrot Cake'], ['Steak', 'Chicken']]
def function(list_contains,word_to_know):
for x in list_contains:
for y in x:
if word_to_know in y:
return list_contains.index(x)
print(function(lst,"Carrot"))
You can use something like this:
def find_index(l,c):
for i,v in enumerate(l):
for j in v:
if c in j:
return i
res = find_index(lst, 'Carrot')
You can use any() with a generator expression to determine whether any item in a sublist contains the target string, then return that sublist's index if so.
def find_index(l, c):
for i, v in enumerate(l):
if any(c in x for x in v):
return i
Well in the question you mention that you know you are only looking at the first level of the list. So in fact you are trying to match a str to a list which will always give you False. You need to make another iteration over each of the inner lists.
In the following code I made a few modifications to make it a bit more readable:
names of variables are better to have a meaning, especially when there are multiple variables involved.
The return of the function is -1 if no match was found, which is a more common convention than returning None, but of course it is OK to return None as well.
def index_of_substr(l, substr):
for i, inner_list in enumerate(l):
for text in inner_list:
if substr in text:
return i
return -1
lst = [['Apple Pie', 'Carrot Cake'], ['Steak', 'Chicken']]
res = index_of_substr(lst, 'Carrot')
print(res)
and the output is 0 of course.
I am a fresh python beginner and trying to extract the first element of the first n-th elements of a nested list. But it doesn't work so far.
Say:
list = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
Goal:
list_new = ['Anna','Peter','Zani'...(#until the n-th elements)]
If I want to first element of all the elements in the list, it should be:
for i in list:
for j in i:
print j[0]
But what if i only want to strip the first element of the n-th elements of the list, instead of all the elements.
For example for the first 2 elements:
I tried:
for i in list[0:2]:
for j in i:
print j[0]
but it didn't work.
What's more, if i want to give the value of n later by using
def sheet(list, n)
and the return statement, how could i do it?
Thank you very much!!
lst = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
n = 2
print(lst[n][0])
Output:
Zani
---Updated answer for the details added in the question---
l = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
n = 2
for i in range(n):
print(l[i][0])
Output:
Anna
Peter
You can use a list comprehension. Given an input list of lists L:
L_new = [i[0] for i in L[:n]]
Functionally, you can use operator.itemgetter. In addition, you can use itertools.islice to avoid creating an intermediary list:
from operator import itemgetter
from itertools import islice
L_new = list(map(itemgetter(0), islice(L, 0, n)))
Be careful, list is reserved for the built-in function list() in python, you should not use 'list' as variable name.
To get the first element of each nested list :
l = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
for e in l:
print(e[0])
Prints :
Anna
Peter
Zani
Lily
To do the same on the nth first elements :
def sheet(l, n):
return [e[0] for e in l[:n]]
sheet(l, 3)
Returns
['Anna', 'Peter', 'Zani']
EDIT
def sheet(l, n):
for e in l[:n]
return [e[0]]
This code only returns ['Anna'] because the return statement stops the function. The for loop is stopped at the first element.
def sheet(l, n):
return [e[0] for e in l[:n]]
is equivalent to :
def sheet(l, n):
result = [e[0] for e in l[:n]]
return result
which is equivalent to :
def sheet(l, n):
result = []
for e in l[:n]:
result.append(e[0])
return result
The for loop can ends before the return statement.
More informations here.
Just try this one which will be easier for you to understand:
n = int(input())
lst = [["Anna","w",15],["Peter","m",20],["Zani","m",10], ["Lily","w",19]]
lst_new = []
for item in lst[:n]:
name, *rest = item
lst_new.append(name)
I would like to remove a certain number of duplicates of a list without removing all of them. For example, I have a list [1,2,3,4,4,4,4,4] and I want to remove 3 of the 4's, so that I am left with [1,2,3,4,4]. A naive way to do it would probably be
def remove_n_duplicates(remove_from, what, how_many):
for j in range(how_many):
remove_from.remove(what)
Is there a way to do remove the three 4's in one pass through the list, but keep the other two.
If you just want to remove the first n occurrences of something from a list, this is pretty easy to do with a generator:
def remove_n_dupes(remove_from, what, how_many):
count = 0
for item in remove_from:
if item == what and count < how_many:
count += 1
else:
yield item
Usage looks like:
lst = [1,2,3,4,4,4,4,4]
print list(remove_n_dupes(lst, 4, 3)) # [1, 2, 3, 4, 4]
Keeping a specified number of duplicates of any item is similarly easy if we use a little extra auxiliary storage:
from collections import Counter
def keep_n_dupes(remove_from, how_many):
counts = Counter()
for item in remove_from:
counts[item] += 1
if counts[item] <= how_many:
yield item
Usage is similar:
lst = [1,1,1,1,2,3,4,4,4,4,4]
print list(keep_n_dupes(lst, 2)) # [1, 1, 2, 3, 4, 4]
Here the input is the list and the max number of items that you want to keep. The caveat is that the items need to be hashable...
You can use Python's set functionality with the & operator to create a list of lists and then flatten the list. The result list will be [1, 2, 3, 4, 4].
x = [1,2,3,4,4,4,4,4]
x2 = [val for sublist in [[item]*max(1, x.count(item)-3) for item in set(x) & set(x)] for val in sublist]
As a function you would have the following.
def remove_n_duplicates(remove_from, what, how_many):
return [val for sublist in [[item]*max(1, remove_from.count(item)-how_many) if item == what else [item]*remove_from.count(item) for item in set(remove_from) & set(remove_from)] for val in sublist]
If the list is sorted, there's the fast solution:
def remove_n_duplicates(remove_from, what, how_many):
index = 0
for i in range(len(remove_from)):
if remove_from[i] == what:
index = i
break
if index + how_many >= len(remove_from):
#There aren't enough things to remove.
return
for i in range(index, how_many):
if remove_from[i] != what:
#Again, there aren't enough things to remove
return
endIndex = index + how_many
return remove_from[:index+1] + remove_from[endIndex:]
Note that this returns the new array, so you want to do arr = removeCount(arr, 4, 3)
Here is another trick which might be useful sometimes. Not to be taken as the recommended recipe.
def remove_n_duplicates(remove_from, what, how_many):
exec('remove_from.remove(what);'*how_many)
I can solve it in different way using collections.
from collections import Counter
li = [1,2,3,4,4,4,4]
cntLi = Counter(li)
print cntLi.keys()
Can anyone tell me how can I call for indexes in a nested list?
Generally I just write:
for i in range (list)
but what if I have a list with nested lists as below:
Nlist = [[2,2,2],[3,3,3],[4,4,4]...]
and I want to go through the indexes of each one separately?
If you really need the indices you can just do what you said again for the inner list:
l = [[2,2,2],[3,3,3],[4,4,4]]
for index1 in xrange(len(l)):
for index2 in xrange(len(l[index1])):
print index1, index2, l[index1][index2]
But it is more pythonic to iterate through the list itself:
for inner_l in l:
for item in inner_l:
print item
If you really need the indices you can also use enumerate:
for index1, inner_l in enumerate(l):
for index2, item in enumerate(inner_l):
print index1, index2, item, l[index1][index2]
Try this setup:
a = [["a","b","c",],["d","e"],["f","g","h"]]
To print the 2nd element in the 1st list ("b"), use print a[0][1] - For the 2nd element in 3rd list ("g"): print a[2][1]
The first brackets reference which nested list you're accessing, the second pair references the item in that list.
You can do this. Adapt it to your situation:
for l in Nlist:
for item in l:
print item
The question title is too wide and the author's need is more specific. In my case, I needed to extract all elements from nested list like in the example below:
Example:
input -> [1,2,[3,4]]
output -> [1,2,3,4]
The code below gives me the result, but I would like to know if anyone can create a simpler answer:
def get_elements_from_nested_list(l, new_l):
if l is not None:
e = l[0]
if isinstance(e, list):
get_elements_from_nested_list(e, new_l)
else:
new_l.append(e)
if len(l) > 1:
return get_elements_from_nested_list(l[1:], new_l)
else:
return new_l
Call of the method
l = [1,2,[3,4]]
new_l = []
get_elements_from_nested_list(l, new_l)
n = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
def flatten(lists):
results = []
for numbers in lists:
for numbers2 in numbers:
results.append(numbers2)
return results
print flatten(n)
Output: n = [1,2,3,4,5,6,7,8,9]
I think you want to access list values and their indices simultaneously and separately:
l = [[2,2,2],[3,3,3],[4,4,4],[5,5,5]]
l_len = len(l)
l_item_len = len(l[0])
for i in range(l_len):
for j in range(l_item_len):
print(f'List[{i}][{j}] : {l[i][j]}' )