0

I have referred to this post for finding the index(ices) corresponding to a single named element in a list, but have not been able to find an answer to my query among the answers there/documentation.

Specifically: is there a more efficient way than just iterating the method in the link above, for finding the indices corresponding to a set of elements?

Say I have the list

mybiglist=['abc','def','ghi','jkl','mno']

and I want the indices corresponding to 'abc','jkl'

I could do:

mytargetlist=['abc','jkl']
for string in mytargetlist:
    print(mybiglist.index('%s' %string))

But it feels like there should be a more efficient way than a loop?

In case the context makes a difference, I am trying to find the indices corresponding to certain vertices in a graph, so that I can use induce_subgraph to create a subgraph containing these vertices. Unfortunately I only know the name labels that I want, and which are attributed to the vertices, and the arguments of induce_subraph are: induce_subgraph(graph, vertex set)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Meep
  • 351
  • 1
  • 4
  • 15
  • note: `('%s' % string)` is equivalent to just `string` – Adam.Er8 Jun 27 '19 at 13:36
  • 1
    Just curious, why do you do `index('%s' %string)` but not `index(string)`? – Quang Hoang Jun 27 '19 at 13:36
  • It seems you want to optimize a graph algorithm. Maybe you could show the used data structure for a graph. With a better context, a better answer could be provided. – S. Lundy Jun 27 '19 at 13:44
  • @QuangHoang For some bizarre reason my code wasn't working with just (string), and I've ben working on it for a week solid so writing it this way has just stuck. Soon as I figure out that bug, I'll polish the code. – Meep Jun 27 '19 at 13:45

4 Answers4

1

You can do it once through your big list with a comprehension.

mybiglist=['abc','def','ghi','jkl','mno']
mytargetlist=['abc','jkl']

[i for i, v in enumerate(mybiglist) if v in mytargetlist]
Kyle Parsons
  • 1,475
  • 6
  • 14
0

I think your way is kind of simple, maybe could be simplified more with list comprehensions (that's just syntactic sugar...):

mybiglist = ['abc', 'def', 'ghi', 'jkl', 'mno']
mytargetlist = ['abc', 'jkl']
print([mybiglist.index(target) for target in mytargetlist])

if you want an overkill solution you can use numpy with isin and where to get the indices without iterating over it yourself:

import numpy as np

mybiglist = np.array(['abc', 'def', 'ghi', 'jkl', 'mno'], dtype=str)
mytargetlist = ['abc', 'jkl']

print(*np.where(np.isin(mybiglist, mytargetlist)))

but that seems a little ridiculous :P

Adam.Er8
  • 12,675
  • 3
  • 26
  • 38
0

mybiglist.index(string) has complexity O(n), so basically you do a double for loop on mybiglist and mytargetlist. You could improve by enumerate:

indices = {v:i for i,v in enumerate(mybiglist)}

and you can access the indices later, i.e. indices['abc'].

Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
0

This will split your target list in chunks and launch separate threads. More info here:

import concurrent.futures

mybiglist=['abc','def','ghi','jkl','mno']
mytargetlist=['abc','jkl']

def get_index(x):
    return mybiglist.index(x)

with concurrent.futures.ProcessPoolExecutor() as executor:
    results = executor.map(get_index, mytargetlist)

print(list(results))
jsa
  • 397
  • 2
  • 14