Как может я, в Python, выполнять итерации по нескольким 2-м спискам сразу, чисто?

Наконец-то нашел то, что искал, используя только RE lib:

поиск текста и получение значения возле searchkey

words = re.findall(r'\w+', contentwhereyouwanttosearchinside)
index = words.index('SEARCHKEY')

напечатать следующие 3 слово например возле ключа поиска

value1 = words[index + 1:index + 3] 
print(value1)
22
задан Eugene M 9 October 2008 в 20:32
поделиться

10 ответов

Я запустил бы путем записи метода генератора:

def grid_objects(alist, blist):
    for i in range(len(alist)):
        for j in range(len(alist[i])):
            yield(alist[i][j], blist[i][j])

Тогда каждый раз, когда необходимо выполнить итерации по спискам, код похож на это:

for (a, b) in grid_objects(alist, blist):
    if a.is_whatever():
        b.do_something()
15
ответ дан 29 November 2019 в 03:41
поделиться

Если кто-либо интересуется производительностью вышеупомянутых решений, здесь они для 4000x4000 сетки от самого быстрого до самого медленного:

РЕДАКТИРОВАНИЕ : очки Добавленного Brian с izip модификация и выигранный большой суммой!

решение John's также очень быстро, хотя оно использует индексы (я был действительно удивлен видеть это!), тогда как Robert и Brian (с zip) медленнее, чем начальное решение создателя вопроса.

Так позволяют нам представить функция завоевания Brian, поскольку ее не показывают в надлежащей форме нигде в этом потоке:

from itertools import izip
for a_row,b_row in izip(alist, blist):
    for a_item, b_item in izip(a_row,b_row):
        if a_item.isWhatever:
            b_item.doSomething()
32
ответ дан 29 November 2019 в 03:41
поделиться

Вы могли архивировать их. т.е.:

for a_row,b_row in zip(alist, blist):
    for a_item, b_item in zip(a_row,b_row):
        if a_item.isWhatever:
            b_item.doSomething()

Однако издержки архивирования и итерации по объектам могут быть выше, чем Ваш исходный метод, если Вы редко на самом деле используете b_item (т.е. a_item.isWhatever обычно является Ложь). Вы могли использовать itertools.izip вместо zip для сокращения влияния памяти этого, но его все еще, вероятно, попытка быть немного медленнее, если Вам всегда не нужен b_item.

, С другой стороны, рассматривают использование 3D списка вместо этого, таким образом, ландшафт для ячейки i, j в l [я] [j] [0], возражает в l [я] [j][1] и т.д., или даже объедините объекты, таким образом, можно сделать [я] [j] .terrain, [я] [j] .object и т.д.

[Редактирование] синхронизации DzinX на самом деле шоу, что влияние дополнительной проверки на b_item не является действительно значительным, рядом с потерей производительности перевзгляда индексом, таким образом, вышеупомянутое (использующий izip), кажется, является самым быстрым.

я теперь дал быстрый тест для 3-го подхода также, и кажется быстрее все еще, поэтому если можно хранить данные в той форме, это могло бы быть и более простым и быстрее к доступу. Вот пример использования его:

# Initialise 3d list:
alist = [ [[A(a_args), B(b_args)] for i in xrange(WIDTH)] for j in xrange(HEIGHT)]

# Process it:
for row in xlist:
    for a,b in row:
        if a.isWhatever(): 
            b.doSomething()

Вот мои синхронизации для 10 циклов с помощью 1000x1000 массив с различными пропорциями isWhatever, который быть верным:

            ( Chance isWhatever is True )
Method      100%     50%      10%      1%

3d          3.422    2.151    1.067    0.824
izip        3.647    2.383    1.282    0.985
original    5.422    3.426    1.891    1.534
10
ответ дан 29 November 2019 в 03:41
поделиться

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

, Например, вот некоторый numpy, использующий код, что я записал, что это делает численное моделирование грубой силы заряженных частиц, соединенных пружинами. Этот код вычисляет такт для 3-й системы с 100 узлами и 99 краями в 31 мс. Это по 10x быстрее, чем лучший чистый код Python, который я мог придумать.

from numpy import array, sqrt, float32, newaxis
def evolve(points, velocities, edges, timestep=0.01, charge=0.1, mass=1., edgelen=0.5, dampen=0.95):
    """Evolve a n body system of electrostatically repulsive nodes connected by
       springs by one timestep."""
    velocities *= dampen

    # calculate matrix of distance vectors between all points and their lengths squared
    dists = array([[p2 - p1 for p2 in points] for p1 in points])
    l_2 = (dists*dists).sum(axis=2)

    # make the diagonal 1's to avoid division by zero
    for i in xrange(points.shape[0]):
        l_2[i,i] = 1

    l_2_inv = 1/l_2
    l_3_inv = l_2_inv*sqrt(l_2_inv)

    # repulsive force: distance vectors divided by length cubed, summed and multiplied by scale
    scale = timestep*charge*charge/mass
    velocities -= scale*(l_3_inv[:,:,newaxis].repeat(points.shape[1], axis=2)*dists).sum(axis=1)

    # calculate spring contributions for each point
    for idx, (point, outedges) in enumerate(izip(points, edges)):
        edgevecs = point - points.take(outedges, axis=0)
        edgevec_lens = sqrt((edgevecs*edgevecs).sum(axis=1))
        scale = timestep/mass
        velocities[idx] += (edgevecs*((((edgelen*scale)/edgevec_lens - scale))[:,newaxis].repeat(points.shape[1],axis=1))).sum(axis=0)

    # move points to new positions
    points += velocities*timestep
4
ответ дан 29 November 2019 в 03:41
поделиться

Как небольшое изменение стиля, Вы могли использовать, перечислите:

for i, arow in enumerate(alist):
    for j, aval in enumerate(arow):
        if aval.isWhatever():
            blist[i][j].doSomething()

я не думаю, что Вы получите что-либо значительно более простое, если Вы не перестроите свои структуры данных, как Federico предполагает. Так, чтобы Вы могли превратить последнюю строку во что-то как "aval.b.doSomething ()".

3
ответ дан 29 November 2019 в 03:41
поделиться

Вы уверены, что объекты в этих двух матрицах, которых Вы выполняете итерации параллельно, являются экземплярами концептуально отличных классов? Что относительно того, чтобы объединить эти два класса, заканчивающиеся с матрицей объектов, которые содержат оба isWhatever () и doSomething ()?

2
ответ дан 29 November 2019 в 03:41
поделиться

Если эти два 2D списка остаются постоянными в течение времени жизни Вашей игры и , Вы не можете наслаждаться множественным наследованием Python для присоединения к alist [я] [j] и blist [я] [j] классы объектов (как другие предположили), Вы могли добавить указатель на соответствие объект b в каждом объект после того, как списки создаются, как это:

for a_row, b_row  in itertools.izip(alist, blist):
    for a_item, b_item in itertools.izip(a_row, b_row):
        a_item.b_item= b_item

Различные оптимизации могут применяться здесь, как Ваши классы, определяющие __slots__, или код инициализации выше мог быть объединен с Вашим собственным e.t.c кода инициализации. После этого Ваш цикл станет:

for a_row in alist:
    for a_item in a_row:
        if a_item.isWhatever():
            a_item.b_item.doSomething()

, Который должен быть более эффективным.

1
ответ дан 29 November 2019 в 03:41
поделиться

Если a.isWhatever редко верно, что Вы могли бы создать "индекс" однажды:

a_index = set((i,j) 
              for i,arow in enumerate(a) 
              for j,a in enumerate(arow) 
              if a.IsWhatever())

и каждый раз Вы хотите, чтобы что-то было сделано:

for (i,j) in a_index:
    b[i][j].doSomething()

, Если изменения со временем, то необходимо будет усовершенствовать индекс. Вот почему я использовал набор, таким образом, объекты могут быть добавлены и удалены быстро.

0
ответ дан 29 November 2019 в 03:41
поделиться
for d1 in alist
   for d2 in d1
      if d2 = "whatever"
          do_my_thing()
-4
ответ дан 29 November 2019 в 03:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: