Создать список на основе списка кортежей (значение, индексы) - PullRequest
2 голосов
/ 22 мая 2019

У меня на входе список кортежей со строкой и список целых чисел. Целые числа идут от 1 до n, и они появляются не более одного раза:

l = [('red', [0,2,5]),
     ('yellow', [1,4]),
     ('red', [6])]

Я хочу создать список из n строк, где, если индекс появится в одном из списков, его значением будет соответствующая строка, а если он не появится, будет применено значение по умолчанию, например white.

Это ожидаемый результат:

result = ['red', 'yellow', 'red', 'white', 'yellow', 'red', 'red']

Это мой код, он отлично работает, но мне интересно есть ли более быстрый способ сделать это :

result = ['white'] * n

for t in l:
    for i in t[1]:
        result[i] = t[0]

Edit:

Я забыл сказать, что n это около 300.

Ответы [ 3 ]

4 голосов
/ 22 мая 2019

Для всех "есть ли более быстрый способ сделать это" вопросы в python (и, я полагаю, в большинстве языков), ответ: измерьте его, тогда вы будете знать .

Я взял код в ответах, предложенных до сих пор, и рассчитал его время:

import numpy as np
import timeit

n = 7
l = [('red', [0,2,5]),
     ('yellow', [1,4]),
     ('red', [6])]

def OP_approach():
    result = ['white'] * n
    for t in l:
        for i in t[1]:
            result[i] = t[0]
    return result

def yatu_approach():
    d = {j:i[0] for i in l for j in i[1]}
    return [d.get(i, 'white') for i in range(len(d)+1)]

def blue_note_approach():
    x = np.empty(7, dtype='<U5')
    x.fill('white')
    for a, b in l:
        x[b] = a
    return x

timeit.timeit(OP_approach, number=10000)
timeit.timeit(yatu_approach, number=10000)
timeit.timeit(blue_note_approach, number=10000)

К моему удивлению, это результат на моей машине (плате arm64):

>>> timeit.timeit(OP_approach, number=10000)
0.033418309001717716
>>> timeit.timeit(yatu_approach, number=10000)
0.10994336503790691
>>> timeit.timeit(blue_note_approach, number=10000)
0.3608954470255412

Похоже, что для данных выборки простой двойной цикл выполняется быстрее, чем оба других варианта.Имейте в виду, однако, что, как отмечает @yatu, эти алгоритмы масштабируются очень по-разному, и выбор того, что использовать, зависит от ожидаемого размера решаемой проблемы.

2 голосов
/ 22 мая 2019

Только при использовании numpy

import numpy as np
x = np.empty(7, dtype='<U6')
x.fill('white')

for a, b in l:
    x[b] = a

, где U6 означает строку в кодировке Unicode длиной 6 (не более)

1 голос
/ 22 мая 2019
from operator import itemgetter

l = [('red', [0,2,5]),
     ('yellow', [1,4]),
     ('red', [6])]
# get len of result
n = max(l, key = itemgetter(1))[1] 

# initialize the result list
result = ['white'] * 7

for t in l:
    for i in t[1]:
        result[i] = t[0]

Выход:

result = ['red', 'yellow', 'red', 'white', 'yellow', 'red', 'red']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...