Я хочу создать определенные пары в массиве numpy, и я показываю, что хочу, с помощью простой функции печати. У меня есть два массива:
points=np.arange(1,15)
Тогда у меня есть другой массив:
repetition= np.array([4, 4, 2, 2, 1, 1])
Теперь я хочу напечатать следующие пары (я только что написал комментарий, чтобы показать, что я хочу):
1 5 # first value of points and (1+4)th value of point
2 6 # second value of points and (2+4)th value of point
3 7 # third value of points and (3+4)th value of point
4 8 # fourth value of points and (3+4)th value of point
7 9 # seventh value of points and (6+2)th value of point
8 10 # eighth value of points and (8+2)th value of point
9 11 # ninth value of points and (9+2)th value of point
10 12 # tenth value of points and (10+2)th value of point
12 13 # twelfth value of points and (11+2)th value of point
13 14 # thirteenth value of points and (13+1)th value of point
Я попробовал следующий код, но он не дал ожидаемого результата:
for m, n in zip (points, repetition):
print (m, m+n)
На рисунке я визуализировал свой вопрос, в котором красные линии показывают мои пары. Я ценю любую помощь заранее.
У меня есть некоторые моменты. Я соединяю эти точки, чтобы создать линии. Затем я хочу создать поверхности, используя эти строки, которые я снова застрял на этом шаге :-(. Я хочу создать поверхности в пакетах Python.
Ага, понятно. Полагаю, вы знакомы с триангуляцией Делоне ? Кстати, Matplotlib при желании использует этот алгоритм для вас в своем классе Triangulation. (Дорожка памяти: я помню, еще в начале девяностых реализовывал очень быстро Делоне (и Вороного) на C).
Я немного знаком с триангуляцией Делоне, но я использую пакет Python под названием gmsh [gmsh.info/], который создает для меня сетку. Мне просто нужно импортировать в него точки. Затем, указав количество баллов (которое ваше решение делает для меня), он создает линии. Затем мне нужно соединить линии для создания поверхностей и, наконец, создать сетку на основе поверхностей.
Вы действительно можете сделать все это в Python. Поскольку ваше изображение, кажется, указывает на рваные массивы, сделать это в numpy
может быть немного сложнее.
from itertools import islice, zip_longest, count, tee
def pairwise(iterable): # as per itertools recipes
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def idx_pairs(repetitions):
it = count()
z = [list(islice(it, n))[::-1] for n in repetitions]
idx = sorted([
(i, j) for seq in zip_longest(*z)
for i, j in pairwise([k for k in seq if k is not None])])
return idx
[(points[i], points[j]) for i, j in idx_pairs(repetition)]
Выход:
[(1, 5),
(2, 6),
(3, 7),
(4, 8),
(7, 9),
(8, 10),
(9, 11),
(10, 12),
(12, 13),
(13, 14)]
Для лучшего понимания шагов предлагаю осмотреть:
z
idx
list(zip_longest(*z))
Последний, в частности (сделанный непосредственно по точкам, а не по индексам точек), показывает что-то очень похожее на рисунок ОП:
it = iter(points)
z = [list(islice(it, n))[::-1] for n in repetition]
list(zip_longest(*z))
# out:
[(4, 8, 10, 12, 13, 14),
(3, 7, 9, 11, None, None),
(2, 6, None, None, None, None),
(1, 5, None, None, None, None)]
Кстати, интересно посмотреть, что происходит, когда список repetition
не монотонно убывает:
repetition = np.array([4, 2, 4, 2, 1, 1])
it = iter(points)
z = [list(islice(it, n))[::-1] for n in repetition]
list(zip_longest(*z))
# out:
[(4, 6, 10, 12, 13, 14),
(3, 5, 9, 11, None, None),
(2, None, 8, None, None, None),
(1, None, 7, None, None, None)]
Я считаю, что правильный вывод для такого repetition
должен быть:
[(1, 7),
(2, 8),
(3, 5),
(4, 6),
(5, 9),
(6, 10),
(9, 11),
(10, 12),
(12, 13),
(13, 14)]
Ради интереса, очки могут содержать что угодно; Вот пример со строками:
points = [
'foo', 'bar', 'hi', 'hello', 'world',
'fuzz', 'ball', 'apple', 'tom', 'nancy',
'fred', 'james', 'mary', 'bob', 'lisa',
]
repetition = np.array([4, 2, 4, 2, 1, 1])
[(points[i], points[j]) for i, j in idx_pairs(repetition)]
# out:
[('foo', 'ball'),
('bar', 'apple'),
('hi', 'world'),
('hello', 'fuzz'),
('world', 'tom'),
('fuzz', 'nancy'),
('tom', 'fred'),
('nancy', 'james'),
('james', 'mary'),
('mary', 'bob')]
упс -- исправление небольшой ошибки: если повторения не монотонно уменьшаются... (например, [4, 2, 4, 2, 1, 1]
...
Уважаемый @Pierre D, он не генерирует то, что я искал. Извините, теперь я понял.
Я уже исправил это - вы видите проблему?
К сожалению, да, например, он дает мне (5, 9)
, пока я хочу (7, 9)
и так далее. Если вы проверите рис или мой ожидаемый результат с помощью pairs
, вы увидите различия. Я ценю вашу помощь и благодарю за то, что уделили время моей проблеме.
О, я вижу: оборванные списки нужно было перевернуть. Простое исправление - см. обновленный ответ.
Только после объяснения @Pierre D. я действительно понял проблему. Спасибо. Я исправил свой предыдущий код и добавил внутрь функцию печати, чтобы упростить интерпретацию.
points=np.arange(1,15)
repetition= np.array([4, 4, 2, 2, 1, 1])
L=[]
k=0
for r in repetition:
last= k+r
L.append(points[k:last])
k= last
print(L,"\n")
lmax= len(max(L,key=len))
L=[ np.concatenate((np.full(lmax-len(l),None),l)) for l in L ]
print(*L,"\n",sep = "\n")
print(*zip(*L),"\n",sep = "\n")
L= [ [ e for e in l if e] for l in zip(*L) ]
print(*L,"\n",sep = "\n")
P= sorted([ p for l in L for p in zip(l,l[1:]) ])
print(*P,"\n",sep = "\n")
это не работает в случае, когда repetition = np.array([4, 2, 4, 2, 1, 1])
. Я считаю, что правильный вывод в этом случае должен быть: [(1, 7), (2, 8), (3, 5), (4, 6), (5, 9), (6, 10), (9, 11), (10, 12), (12, 13), (13, 14)]
.
@Pierre D Вы правы. Я исправил код выше.
Я думал об этом; из любопытства, что за приложение?