преобразовать / отобразить словарь Python в список, используя ключ в качестве индекса списка - PullRequest
0 голосов
/ 16 октября 2018

У меня есть словарь Python следующим образом:

dict = {4:0.65,8:1.23,3:0.43}

Я хотел бы преобразовать это в список Python, используя ключ в качестве индекса для списка.Желаемый преобразованный результат будет:

listLength = 10
plist = [0,0,0,0.43,0.65,0,0,0,1.23,0]

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

Мне особенно нужно сделать вышеупомянутое с лучшей производительностью.

Ответы [ 7 ]

0 голосов
/ 16 октября 2018

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

  list = [0] * length
    for key, val in d.items():
        if key < length:
            list[key] = val

Если вы хотите, чтобы список был таким же большим, как ключ макс, следуйте этому ниже

maxKey = max(d, key=int)
list = [0] * maxKey
for key, val in d.items():
    list[key] = val
0 голосов
/ 16 октября 2018

Для больших наборов данных вы можете получить некоторую скорость, используя np.fromiter непосредственно на итераторах ключей и значений вместо того, чтобы сначала создавать списки.

Создать тестовый набор

>>> d = dict(zip(np.random.randint(1, 10, 1_000_000).cumsum(), np.arange(1_000_000.)))
>>> out = np.zeros(10_000_000)

Определить fromiter method

>>> def use_iter():
...     k, v = (np.fromiter(w, dtype=t, count=len(d)) for w, t in [(d.keys(), int), (d.values(), float)])
...     out[k] = v
...     return out

и list метод для справки

>>> def use_list():
...     out[list(d.keys())] = list(d.values())
...     return out

и время их

>>> timeit(use_iter, number=100)
4.2583943260106025
>>> timeit(use_list, number=100)
17.10310926999955

Также проверьте правильность

>>> np.all(use_list() == use_iter())
True
0 голосов
/ 16 октября 2018

Использование индексирования numpy и numpy будет наиболее эффективным решением:

out = np.zeros(10)
out[list(d.keys())] = list(d.values())

array([0.  , 0.  , 0.  , 0.43, 0.65, 0.  , 0.  , 0.  , 1.23, 0.  ])

Производительность так как вы спросили:

k = np.random.randint(1, 100000, 10000)
v = np.random.rand(10000)
d = dict(zip(k, v))

In [119]: %%timeit
     ...: out = np.zeros(100000)
     ...: out[list(d.keys())] = list(d.values())
     ...:
     ...:
1.86 ms ± 13.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [120]: %timeit [d.get(i, 0) for i in range(100000)]
17.4 ms ± 231 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [121]: %timeit pd.Series(d).reindex(range(100000),fill_value=0).tolist()
9.77 ms ± 148 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
0 голосов
/ 16 октября 2018

Так как вы помечаете pandas, решение от reindex

pd.Series(d).reindex(range(10),fill_value=0).tolist()
Out[369]: [0.0, 0.0, 0.0, 0.43, 0.65, 0.0, 0.0, 0.0, 1.23, 0.0]
0 голосов
/ 16 октября 2018

Использование списка понимания

lst = [d[i] if i in d else 0 for i in range(10)]
print(lst)
# [0, 0, 0, 0.43, 0.65, 0, 0, 0, 1.23, 0]

Расширено:

lst = []
for i in range(10):
    if i in d:
        lst.append(d[i])
    else:
        lst.append(0)
0 голосов
/ 16 октября 2018

Избегайте затенения встроенного dict.Вместо этого используйте другое имя.

dict_ = {4:0.65,8:1.23,3:0.43}
length = max(dict_) + 1  # Get number of entries needed
list_ = [0] * length  # Initialize a list of zeroes
for i in dict_:
    list_[i] = dict_[i]
0 голосов
/ 16 октября 2018

Вы можете примерно так:

list_length = 10
d = {4: 0.65, 8: 1.23, 3: 0.43}
plist = [d.get(i, 0) for i in range(list_length)]

print(plist)

Вывод

[0, 0, 0, 0.43, 0.65, 0, 0, 0, 1.23, 0]

Примечание: Не использовать имя dictдля ваших собственных переменных вы будете скрывать встроенное имя dict.

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