LINUX.ORG.RU

Быстро посчитать вхождение элементов одного списка в другой Python

 , ,


0

1

Сейчас делаю так:

for elem in list1:
    counter = 0
    for elem2 in list2:
        # тут некоторый медленный код обработки, который я выкинул в примере, переписывать его на сишку нельзя, это модуль на питоне
        if elem2 == elem:
            counter += 1
    sub_list.append(counter)
list1 содержит от 10 до 20 000 элементов, в среднем 6 000 элементов, list2 содержит около пары тысяч элементов. list2 у меня динамически грузится с жесткого диска в ещё одном внешнем цикле, их около 10 000. Как-то печально всё со скоростью перелопачивания. sub_list это на самом деле строки для csv файла, который я пытаюсь сгенерировать. Это как-то можно быстрее делать, например, внеся батарейки на сишке, помазав всё лямбдами или как-то ещё (на первый взгляд кажется что нельзя)? А то чувствую до утра считать будет. Не к спеху, конечно, всего 4 раза посчитать надо будет с разными параметрами, но на будущее хочется знать.

★★★★★

Последнее исправление: peregrine (всего исправлений: 1)

Самое эффективное решение этой задачи - сохранить данные не в два списка, а в два множества (set/frozenset) и взять их пересечение (intersection). Для лучшего понимания стоит почитать структуры данных и алгоритмические сложности их методов.

anonymous
()

В списках повтояющиеся элементы есть? Их нужно один раз обрабатывать или несколько? Если нет и/или надо обрабатывать только один раз, то можно так:

for elem in set(list1) & set(list2):
    pass
TeopeTuK ★★★★★
()
Ответ на: комментарий от TeopeTuK

Есть, именно по этому там counter += 1. Точнее в list1 гарантированно нет повторений, но мне важен порядок в котором будет sub_list. А вот в list2 точно есть повторения и вообще всякое разное. Немного ошибся в первом посте, поправлю сейчас.

peregrine ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Это я знаю. Тут проблема в том, что мне не факт вхождения нужен, а количество для каждого отдельного вхождения.

peregrine ★★★★★
() автор топика
Ответ на: комментарий от peregrine

посмотри в сторону collections.Counter, возможно пригодится.

gnunixon ★★★
()

Из list2 делаешь словарь {elem: кол_во_вхождений, …}, проверка вхождения сводится к простому list2.get(elem, 0)

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

О, вот это уже интереснее. Спасибо. Чёт не подумал сразу.

peregrine ★★★★★
() автор топика

Лень разбираться, что именно ты делаешь, но не difflib ли тебе нужен?

WitcherGeralt ★★
()
map2 = dict()

for i in list2:
    if i in map2:
        map2[i] += 1
    else:
        map2[i] = 1

for i in list1:
    if i in map2:
        sub_list.append(map2[i])
    else:
        sub_list.append(0)

как-то так, наверное.

xpahos ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Это сейчас повод посраться на пару страниц - сразу рассказывать про все батарейки стандартной бибилиотеки или для начала обойтись встроенными типами.

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)

Если в питоне можно преобразовать true и false в int, то тогда можно посчитать примерно так (powershell):

$a = 1,2,3,4,5,6,7,8,9,0,2,2,3,4,5,6,6,7,8,9,0
$b = 5,6,7,1,1,1,1,2,3,4,5,5,5,9,8,2,6,0,0,4,4,3,5,5,8

# оставляем только уникальные элем.
$a_sorted = $a | sort -unique

# пустая таблица (именованный список)
$hash = @{}

foreach ($element in $b)
{
    $hash[$element] += [int] ($e -in $a_sorted)     # $true = 1
}

$hash
anonymous
()
Ответ на: комментарий от anonymous

Преобразовать нельзя, потому что они фактически и есть int

beresk_let ★★★★★
()

result_dict = {i: list2.count(i) for i in list1}

zad1ra
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.