Как найти, какие строки в массиве являются подстроки в другой строке в Python? - PullRequest
0 голосов
/ 11 июля 2019

У меня есть массив строк (str8192), где второй столбец - это имена вещей. Ради этого, допустим, этот массив называется thingList. У меня есть две строки, string1 и string2. Я пытаюсь получить список каждого элемента во втором столбце thingList, который находится в строке 1 или в строке 2. В настоящее время у меня это работает с циклом for, но я надеялся, что был более быстрый способ, я не знаю о, я довольно новичок в программировании.

Как только я найду совпадение, я также хочу записать, что находится в первом столбце, но в той же строке, что и совпадение.

Любая помощь для ускорения это очень ценится, так как thingList довольно большой, и эти функции довольно часто запускаются с различными массивами.

tempThing = []
tempCode = []

for i in range(thingList.shape[0]):
        if thingList[i][1].lower() in string1.lower() or thingList[i] [1].lower() in string2.lower():
            tempThing.append(thingList[i][1])
            tempCode.append(thingList[i][0])

Этот код работает нормально, но он определенно является узким местом в моей программе и сильно его тормозит.

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Массивы Numpy по умолчанию будут перебирать строки, поэтому нет необходимости делать for i in range(...):

x = np.array(list(range(3)), list(range(3,6)))

for i in x:
    print(i)

[0 1 2]
[3 4 5]

# This yields the same result, so use the former
for i in range(x.shape[0]):
    print(x[i])

[0 1 2]
[3 4 5]

Далее, вы тратите кучу времени на выполнение str.lower() снова и снова.Я бы, вероятно, заранее опустил все ваши строки заранее:

y = np.array([list('ABC'), list('DEF')])

np.char.lower(y)
array([['a', 'b', 'c'],
       ['d', 'e', 'f']],
      dtype='<U1')

# apply this to string1 and string2
l_str1, l_str2 = string1.lower(), string2.lower()

Теперь ваш цикл должен выглядеть следующим образом:

l_str1, l_str2 = string1.lower(), string2.lower()

for val1, val2 in thingList:
    to_check = val2.lower()

    if to_check in l_str1 or to_check in l_str2:
        tempThing.append(val1)
        tempCode.append(val2)

Теперь вы можете применить это к пониманию списка:

# you can zip these together so you aren't using str.lower() 
# for all of your if statements
tmp = ((*uprow) for uprow, (a, b) in zip(thingList, np.char.lower(thingList))
       if b in l_str1 or b in l_str2)

# this will unpack pairs
tempThing, tempCode = zip(*tmp)
0 голосов
/ 11 июля 2019

Вы можете использовать списочные выражения, они быстрее, чем традиционные для циклов. Кроме того, есть несколько небольших улучшений, которые вы можете сделать, чтобы ваш код работал быстрее:

thing_list = [['Thing1', 'bo'], ['Thing2', 'b'], [ 'Thing3', 'ca'],
              ['Thing4', 'patrick']]*100
string1 = 'bobby'
string2 = 'patrick neils'

# Compute your lower strings before the for loops to avoid
# calling the function at each loop
st1_lower = string1.lower()
st2_lower = string2.lower()

# You can store both the item and the name in the same array to reduce
# the computing time and do it in one list comprehension
result = [[x[0], x[1]] for x in thing_list
          if (x[1].lower() in st1_lower) or (x[1].lower() in st2_lower) ]

Выход:

[['Thing1', 'bo'], ['Thing2', 'b'], ['Thing4', 'patrick']]

Производительность:

Для циклов: 172 мкс ± 9,59 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, 10000 циклов в каждом)

Понимание списка: 81,1 мкс ± 2,17 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, 10000 циклов каждый)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...