Search in Lists of Lists by Given Index

Search in lists of lists by given index

You're always going to have a loop - someone might come along with a clever one-liner that hides the loop within a call to map() or similar, but it's always going to be there.

My preference would always be to have clean and simple code, unless performance is a major factor.

Here's perhaps a more Pythonic version of your code:

data = [['a','b'], ['a','c'], ['b','d']]
search = 'c'
for sublist in data:
if sublist[1] == search:
print "Found it!", sublist
break
# Prints: Found it! ['a', 'c']

It breaks out of the loop as soon as it finds a match.

(You have a typo, by the way, in ['b''d'].)

Find the index of an item in a list of lists

I'd do something like this:

[(i, colour.index(c))
for i, colour in enumerate(colours)
if c in colour]

This will return a list of tuples where the first index is the position in the first list and second index the position in the second list (note: c is the colour you're looking for, that is, "#660000").

For the example in the question, the returned value is:

[(0, 0)]

If you just need to find the first position in which the colour is found in a lazy way you can use this:

next(((i, colour.index(c))
for i, colour in enumerate(colours)
if c in colour),
None)

This will return the tuple for the first element found or None if no element is found (you can also remove the None argument above in it will raise a StopIteration exception if no element is found).

Edit: As @RikPoggi correctly points out, if the number of matches is high, this will introduce some overhead because colour is iterated twice to find c. I assumed this to be reasonable for a low number of matches and to have an answer into a single expression. However, to avoid this, you can also define a method using the same idea as follows:

def find(c):
for i, colour in enumerate(colours):
try:
j = colour.index(c)
except ValueError:
continue
yield i, j

matches = [match for match in find('#660000')]

Note that since find is a generator you can actually use it as in the example above with next to stop at the first match and skip looking further.

Process a list of lists, finding all lists that have matching last values?

1. Using collections.defaultdict

You can use defaultdict to the first group up your items with more than one occurrence, then, iterate over the dict.items to get what you need.

from collections import defaultdict

lol = [[0,'a'], [0,'b'],
[1,'b'], [1,'c'],
[2,'d'], [2,'e'],
[2,'g'], [2,'b'],
[3,'e'], [3,'f']]

d = defaultdict(list)

for v,k in lol:
d[k].append(v)

# d looks like -
# defaultdict(list,
# {'a': [0],
# 'b': [0, 1, 2],
# 'c': [1],
# 'd': [2],
# 'e': [2, 3],
# 'g': [2],
# 'f': [3]})

result = [[v,k] for k,vs in d.items() for v in vs if len(vs)>1]
print(result)
[[0, 'b'], [1, 'b'], [2, 'b'], [2, 'e'], [3, 'e']]


2. Using pandas.duplicated

Here is how you can do this with Pandas -

  1. Convert to pandas dataframe
  2. For key column, find the duplicates and keep all of them
  3. Convert to list of records while ignoring index
import pandas as pd

df = pd.DataFrame(lol, columns=['val','key'])
dups = df[df['key'].duplicated(keep=False)]
result = list(dups.to_records(index=False))
print(result)
[(0, 'b'), (1, 'b'), (2, 'e'), (2, 'b'), (3, 'e')]


3. Using numpy.unique

You can solve this in a vectorized manner using numpy -


  1. Convert to numpy matrix arr
  2. Find unique elements u and their counts c
  3. Filter list of unique elements that occur more than once dup
  4. Use broadcasting to compare the second column of the array and take any over axis=0 to get a boolean which is True for duplicated rows
  5. Filter the arr based on this boolean
import numpy as np

arr = np.array(lol)

u, c = np.unique(arr[:,1], return_counts=True)
dup = u[c > 1]

result = arr[(arr[:,1]==dup[:,None]).any(0)]
result
array([['0', 'b'],
['1', 'b'],
['2', 'e'],
['2', 'b'],
['3', 'e']], dtype='<U21')

Python finding a value in a list of lists

Yes, no need for range, for starters

for hay in haystack:
if needle in hay:
return hay

And if you really really need the index, use enumerate

for x, hay in enumerate(haystack):
if needle in hay:
return x

Finding the index of an item in a list of lists

Just use enumerate:

l = [[1,2,3,4],[5,6,7,8,9,10],[11,12,13]]

# e.g.: find the index of the list containing 12
# This returns the first match (i.e. using index 0), if you want all matches
# simply remove the `[0]`
print [i for i, lst in enumerate(l) if 12 in lst][0]

This outputs:

[2]

Edit:

@hlt's comment suggests using the following for more efficient behavior:

next(i for i,v in enumerate(l) if 12 in v)

Using a list of lists containing indexes to pull strings by index from another list

[[list_of_text[idx-1] for idx in indices] for indices in list_of_indexes]

Find a number in list of lists

Lists are not the best data structure to look for elements, you should consider using sets, which gives you O(1) time for lookup. There are better data structures and algorithms if your lists don't have intersections, but since you want all the lists, there are fewer alternatives.

lsts = [[0,1,2,3,4,5], [6,7,8,9,10,11], [12,56,86,9], [55,53,12]]
sets = map(set, lsts)

def find(iterables, element):
return [i for i, iterable in enumerate(iterables) if element in iterable]

How to find index of a given value in a nested list in Python?

Everything seems fine in your code, just make the string formatter a tuple. Modify the last line of your code to this below:

print('the index of 1 is [%d][%d] ' % (item,item2))


Related Topics



Leave a reply



Submit