Как вставлять элементы в вектор через равные промежутки времени - PullRequest
3 голосов
/ 24 мая 2019

У меня есть следующий список.

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

Я хочу получить следующее, вставив каждые два элемента.

output = [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

Хорошо не только список Python, но и ответ с использованием массива numpy.

Ответы [ 5 ]

1 голос
/ 24 мая 2019

Вот подход, основанный на itertools, который также работает для произвольного числа элементов, которые нужно вставить из одного списка в другой.Для этого я определил функцию генератора, которая будет вставлять элемент l2 в l1 каждые i элементов:

def insert_n(l1, l2, i):
    while True:
        try:
            yield from islice(l1, i)
            yield next(l2)
        except StopIteration:
            return

Это работает, давая до iэлементы из итератора l1 на каждой итерации, используя itertools.isliceyield from мы получаем столько элементов, сколько есть в итерируемой части, поэтому итерация запускается до истощения (сокращение для for v in g: yield v).

Наконец мы можемоберните операторы yield try / expect, чтобы перехватить предупреждение StopIteration.


Давайте попробуем с предложенным примером:

vector = iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
inserted_elements = iter([2, 2, 2, 2, 2])

list(insert_every_n(vector, inserted_elements, i=2))
# [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

И еслимы хотели добавить элемент l2 каждые 3 элемента:

vector = iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
inserted_elements = iter([2, 2, 2, 2])

list(insert_every_n(vector, inserted_elements, i=3))
# [1, 2, 3, 2, 4, 5, 6, 2, 7, 8, 9, 2, 10, 2]
1 голос
/ 24 мая 2019

Вот несколько неясный подход - но он быстрее, чем что-либо еще (пока):

list(itertools.chain(*zip(*[iter(vector)]*2+[iter(inserted_elements)]))) 

Используется «идиома» для взятия предметов в группах размера n, [iter(alist)]*n и itertools.chain как способ выравнивания вложенного списка.

Удаленный ответ использовал np.insert.Для этого я считаю, что insert использует маскирование, как показано ниже:

def foo(vector, inserted_elements):
    res = np.zeros(len(vector)+len(inserted_elements),int)  
    mask = res.astype(bool) 
    mask[2::3]=True 
    res[mask]=inserted_elements 
    res[~mask]=vector    
    return res

Вариант ответа np.append:

np.column_stack((np.reshape(vector,(-1,2)), inserted_elements)).ravel()

Мне вообще не нравится np.append, поскольку он часто используется неправильно, особенно в петлях.Для этого все нормально, но я думаю, что column_stack чище.

===

In [254]: list(zip(*[iter(vector)]*2+[iter(inserted_elements)]))                                         
Out[254]: [(1, 2, 2), (3, 4, 2), (5, 6, 2), (7, 8, 2), (9, 10, 2)]
1 голос
/ 24 мая 2019

шаг массива:

1

>>> a=np.reshape(np.matrix([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),(5, 2))
>>> a
matrix([[ 1,  2],
        [ 3,  4],
        [ 5,  6],
        [ 7,  8],
        [ 9, 10]])

2

>>> b=np.reshape(np.matrix([2, 2, 2, 2, 2]),(5, 1))
>>> b
matrix([[2],
        [2],
        [2],
        [2],
        [2]])

3.

>>> M = np.append(a, b, axis=1)
>>> M
matrix([[ 1,  2,  2],
        [ 3,  4,  2],
        [ 5,  6,  2],
        [ 7,  8,  2],
        [ 9, 10,  2]])

4

>>> result=np.array(M).flatten()
>>> result
array([ 1,  2,  2,  3,  4,  2,  5,  6,  2,  7,  8,  2,  9, 10,  2])
1 голос
/ 24 мая 2019

Традиционный подход для цикла может выглядеть следующим образом: вы выбираете 2 элемента из vector и 1 элемент из inserted_elements и создаете список output

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

output = []

#Pick two elements from vector and one element from inserted_elements and add it to output list
for idx in range(0,len(vector),2):

    output.extend(vector[idx:idx+2] + [inserted_elements[int(idx/2)]])

print(output)

То же самоев списке-понимании будет

output = [ v for idx in range(0,len(vector),2) for v in vector[idx:idx+2] + [inserted_elements[int(idx/2)]]]

На выходе будет

[1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]
1 голос
/ 24 мая 2019

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

it1, it2 = map(iter, (vector, inserted_elements))
n = sum(map(len, (vector, inserted_elements)))

[next(it2) if i % 3 == 0 else next(it1) for i in range(1, n+1)]
# [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

Каждые 3 * 1004Элемент * rd в выводе будет получен из it2, итератор для inserted_elements.Остальные приходят от it1, что соответствует vector.

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