Я хочу сжать список объектов с новым объектом, чтобы сгенерировать список координат (2 кортежа), но я хочу заверить, что для (i, j) i
Однако я не очень доволен моими текущими решениями:
from itertools import repeat
mems = range(1, 10, 2)
mem = 8
def ij(i, j):
if i < j:
return (i, j)
else:
return (j, i)
def zipij(m=mem, ms=mems, f=ij):
return map(lambda i: f(i, m), ms)
def zipij2(m=mem, ms=mems):
return map(lambda i: tuple(sorted([i, m])), ms)
def zipij3(m=mem, ms=mems):
return [tuple(sorted([i, m])) for i in ms]
def zipij4(m=mem, ms=mems):
mems = zip(ms, repeat(m))
half1 = [(i, j) for i, j in mems if i < j]
half2 = [(j, i) for i, j in mems[len(half1):]]
return half1 + half2
def zipij5(m=mem, ms=mems):
mems = zip(ms, repeat(m))
return [(i, j) for i, j in mems if i < j] + [(j, i) for i, j in mems if i > j]
Выход для выше:
>>> print zipij() # or zipij{2-5}
[(1, 8), (3, 8), (5, 8), (7, 8), (8, 9)]
Вместо обычно:
>>> print zip(mems, repeat(mem))
[(1, 8), (3, 8), (5, 8), (7, 8), (9, 8)]
Время: отрублено (больше не актуально, смотрите ответы на гораздо более быстрые результаты ниже)
Для len(mems) == 5
нет реальной проблемы с каким-либо решением, но для zipij5 (), например, понимание второго списка без необходимости возвращается к первым четырем значениям, когда i > j
уже было оценено как True
для тех, кто в первом понимании.
Для моих целей я уверен, что len(mems)
никогда не превысит ~ 10000, если это поможет сформировать ответы на вопрос, какое решение лучше. Чтобы немного объяснить мой вариант использования (я нахожу это интересным), я буду хранить разреженную, верхнетреугольную матрицу подобия, и поэтому мне нужна координата (i, j)
, чтобы не дублироваться в (j, i)
. Я говорю своего рода , потому что я буду использовать новый объект Counter()
в 2.7 для выполнения квазиматричной матрицы и матричного вектора-сложения. Затем я просто передаю counter_obj.update()
список из двух кортежей, и он увеличивает эти координаты, сколько раз они встречаются. Редкие матрицы SciPy работали примерно в 50 раз медленнее, к моему ужасу, для моих случаев использования ... поэтому я быстро отказался от них.
Так или иначе, я был удивлен моими результатами ... Первые методы, которые я придумал, были zipij4
и zipij5
, и все же они все еще самые быстрые, несмотря на создание нормального zip()
и затем генерацию новый почтовый индекс после изменения значений. Я все еще довольно новичок в Python, условно говоря (Алекс Мартелли, вы меня слышите?), Поэтому вот мои наивные выводы:
tuple(sorted([i, j]))
очень дорого (почему?)
map(lambda ...)
, кажется, всегда делает хуже, чем список компа (я думаю, что я прочитал это, и это имеет смысл)
- Почему-то
zipij5()
не намного медленнее, несмотря на то, что дважды просматривал список, чтобы проверить неравенство i-j. (Почему это так?)
И, наконец, я хотел бы знать, какой из них считается наиболее эффективным ... или есть ли другие быстрые и недорогие способы, о которых я еще не думал. Спасибо.
Текущие лучшие решения
## Most BRIEF, Quickest with UNSORTED input list:
## truppo's
def zipij9(m=mem, ms=mems):
return [(i, m) if i < m else (m, i) for i in ms]
## Quickest with pre-SORTED input list:
## Michal's
def zipij10(m=mem, ms=mems):
i = binsearch(m, ms) ## See Michal's answer for binsearch()
return zip(ms[:i], repeat(m)) + zip(repeat(m), ms[i:])
Задержка
# Michal's
Presorted - 410µs per loop
Unsorted - 2.09ms per loop ## Due solely to the expensive sorted()
# truppo's
Presorted - 880µs per loop
Unsorted - 896µs per loop ## No sorted() needed
Время использовалось mems = range(1, 10000, 2)
, длина которого всего ~ 5000. sorted()
вероятно станет хуже при более высоких значениях и списках, которые более перемешаны. random.shuffle()
был использован для "несортированных" таймингов.