Ваш вопрос немного сбивает с толку, так как вы вызываете эти массивы NumPy и запрашиваете способ векторизации вещей, но затем показывает списки и помечаете их как списки в вашем примере, и используете список в заголовке. Я предполагаю, что у вас есть массивы.
>>> l1 = np.array([1, 2, 3, 4, 5])
>>> l2 = np.array([6, 7, 8, 9, 10])
>>> l3 = np.array([11, 12, 13, 14, 15])
Если это так, вы можете сложить их в двумерный массив:
>>> ll = np.stack((l1, l2, l3))
И тогда вы можете просто перенести это:
>>> lt = ll.T
Это лучше, чем векторизация; это постоянное время. NumPy просто создает другое представление тех же данных с другим шагом, поэтому оно читает в порядке столбцов, а не строк.
>>> lt
array([[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14],
[ 5, 10, 15]])
Как указывает Мирадуло, вы можете сделать оба этих действия за один шаг с помощью column_stack
:
>>> lt = np.column_stack((l1, l2, l3))
Но я подозреваю, что вы на самом деле захотите ll
как самостоятельное значение. (Хотя, признаюсь, я просто догадываюсь, что вы пытаетесь сделать ...)
И, конечно, если вы хотите зациклить эти строки как одномерные массивы вместо выполнения дальнейшей векторизации, вы можете:
>>> for row in lt:
...: print(row)
[ 1 6 11]
[ 2 7 12]
[ 3 8 13]
[ 4 9 14]
[ 5 10 15]
Конечно, вы можете преобразовать их из одномерных массивов в кортежи, просто вызвав tuple
в каждой строке. Или ... каким бы ни было mydict
(это не похоже на словарь - здесь нет пар ключ-значение, только значения), вы можете сделать это.
>>> mydict = collections.namedtuple('mydict', list('abc'))
>>> tups = [mydict(*row) for row in lt]
>>> tups
[mydict(a=1, b=6, c=11),
mydict(a=2, b=7, c=12),
mydict(a=3, b=8, c=13),
mydict(a=4, b=9, c=14),
mydict(a=5, b=10, c=15)]
Если вас беспокоит время поиска кортежа клавиш в диктовке, itemgetter
в модуле operator
имеет версию с C-ускорением. Если keys
- это np.array
, или tuple
, или что-то еще, вы можете сделать это:
for row in lt:
myvals = operator.itemgetter(*row)(mydict)
# do stuff with myvals
Тем временем я решил собрать вместе расширение C, которое должно быть максимально быстрым (без обработки ошибок, потому что Я ленивый Это должно быть чуть-чуть быстрее - этот код будет вероятно, segfault, если вы дадите ему что-нибудь кроме dict и кортежа или списка):
static PyObject *
itemget_itemget(PyObject *self, PyObject *args) {
PyObject *d;
PyObject *keys;
PyArg_ParseTuple(args, "OO", &d, &keys);
PyObject *seq = PySequence_Fast(keys, "keys must be an iterable");
PyObject **arr = PySequence_Fast_ITEMS(seq);
int seqlen = PySequence_Fast_GET_SIZE(seq);
PyObject *result = PyTuple_New(seqlen);
PyObject **resarr = PySequence_Fast_ITEMS(result);
for (int i=0; i!=seqlen; ++i) {
resarr[i] = PyDict_GetItem(d, arr[i]);
Py_INCREF(resarr[i]);
}
return result;
}
Время поиска 100 случайных ключей из словаря 10000 ключей на моем ноутбуке с python.org CPython 3.7 на macOS:
itemget.itemget
: 1,6 мкс
operator.itemgetter
: 1,8 мкс
- понимание: 3,4 мкс
- чистый Python
operator.itemgetter
: 6,7 мкс
Итак, я уверен, что все, что вы делаете, будет достаточно быстрым - это всего лишь 34 нс / ключ, который мы пытаемся оптимизировать. Но если это действительно слишком медленно, operator.itemgetter
делает достаточно хорошую работу, перемещая цикл в C и разрезая его примерно пополам, что довольно близко к наилучшему результату, который вы могли ожидать. (Трудно представить, что все-таки можно зацикливать связку ключей в штучной упаковке в хеш-таблице намного меньше чем 16 нс / ключ.)