Әрбір x жағдайында 2 тізімді біріктіріңіз

Say I have two lists one longer than the other, x = [1,2,3,4,5,6,7,8] and y = [a,b,c] and I want to merge each element in y to every 3rd index in x so the resulting list z would look like: z = [1,2,a,3,4,b,5,6,c,7,8]

Бұл туралы питонда немен айналысуға болады?

4

8 жауаптар

Мұнда itertools құжаттамасынан жасалған шоколадты рецептінің бейімделген нұсқасы берілген. қалағаныңды жаса:

from itertools import cycle, islice

def merge(a, b, pos):
    "merge('ABCDEF', [1,2,3], 3) --> A B 1 C D 2 E F 3"
    iterables = [iter(a)]*(pos-1) + [iter(b)]
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

Мысал:

>>> list(merge(xrange(1, 9), 'abc', 3))   # note that this works for any iterable!
[1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]

Немесе мұнда roundrobin() қалай қолдануға болатынын білесіз:

>>> x = [1,2,3,4,5,6,7,8]
>>> y = ['a','b','c']
>>> list(roundrobin(*([iter(x)]*2 + [y])))
[1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]

Немесе баламалы, бірақ аздап оқылатын нұсқасы:

>>> xiter = iter(x)
>>> list(roundrobin(xiter, xiter, y))
[1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]

Бұл әдістердің екеуі де тек бірізділікпен емес, кез-келген итеремен жұмыс жасайтынын ескеріңіз.

Мұнда түпнұсқа roundrobin() енгізу:

from itertools import cycle, islice

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))
5
қосылды

Бұл тәсіл орнына x өзгертеді. Сонымен қатар, түпнұсқаны өзгерткіңіз келмесе, x көшірмесін жасай аласыз және өзгертілген көшірмені қайтара аласыз.

def merge(x, y, offset):
    for i, element in enumerate(y, 1):
        x.insert(i * offset - 1, element)

>>> x = [1,2,3,4,5,6,7,8]
>>> y = ['a','b','c']
>>> merge(x, y, 3)
>>> x
[1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]

y соңындағы y барлық қосымша элементтері тек соңына қосылады.

3
қосылды
@ 2rs2ts Келісілді, кірістіру O (n) . Кішігірім деректер жинақтары үшін менің көзқарасым жұмыс істейді, бірақ үлкен жиынтықтар үшін кеңес бермеймін.
қосылды автор Matthew Jacobs, көзі
Менің ойымша, бұл шынымен қайда қолданылатынына байланысты. Егер ол қайта-қайта қоңырау шалынатын циклдің ортасында болса, сіз ең жылдам әдіс туралы қаласаңыз болады. Алайда, егер ол бір рет (кейде кейде) деп аталса, шикізат жылдамдығы өте маңызды болмауы мүмкін. Оны нөмірге қою үшін бірнеше жүз болуы мүмкін. Дегенмен, мен оны неғұрлым маңызды деп санаймын.
қосылды автор Matthew Jacobs, көзі
Маған ұнайды, бұл қарапайым және қысқа, мен оны түсінуге болады! Мен кез-келген шешімдердің орындалуына түсініктеме бере алмаймын, себебі бұл кезде менің түсінігім жоғары.
қосылды автор KingFu, көзі
@ 2rs2s жақсы нәрсе, содан кейін қиындықтар! Мен жауап күтпей тұрып, күтуге және тәжірибелі адамдарға жақсы (жылдам!) Шешім қабылдауға мүмкіндік берер едім
қосылды автор KingFu, көзі
@MatthewJacobs үлкен деректер жиынтығын не деп есептейсіз?
қосылды автор KingFu, көзі
>>> from itertools import chain
def solve(x,y):                                                             
    it = iter(y)
    for i in xrange(0, len(x), 2):
        try:
            yield x[i:i+2] + [next(it)]
        except StopIteration:    
            yield x[i:]
...

>>> x = [1,2,3,4,5,6,7,8]
>>> y = ['a','b','c']

>>> list(chain.from_iterable(solve(x,y)))
[1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]
3
қосылды

Тағы бір жолы:

x = range(1, 9)
y = list('abc')

from itertools import count, izip
from operator import itemgetter
from heapq import merge

print map(itemgetter(1), merge(enumerate(x), izip(count(1, 2), y)))
# [1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]

Бұл жаңа тізімді құрастырмас бұрын барлық жалқауды сақтайды және біріктіру мүмкіндік береді, әрине, бірізділікті біріктіреді ... безендірілген/бейтарап түрі ... Python 2.7 үшін count step аргументіне ие болу үшін.

Мәселен, біраз жолмен жүру:

a = list(enumerate(x))
# [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8)]
b = zip(count(1, 2), y)
# [(1, 'a'), (3, 'b'), (5, 'c')]
print list(merge(a, b))
# [(0, 1), (1, 2), (1, 'a'), (2, 3), (3, 4), (3, 'b'), (4, 5), (5, 6), (5, 'c'), (6, 7), (7, 8)]

Содан кейін itemgetter (1) индексті алып тастаған нақты мәнді ғана алады ...

3
қосылды

Жоғарыда келтірілген шешімдер өте керемет. Мұнда трубкобин немесе итертуэлді қамтымайтын балама бар.

def merge(x, y):
    result = []
    while y:
        for i in range(0, 2): result.append(x.pop(0))
        for i in range(0, 1): result.append(y.pop(0))
    result.extend(x)
    return result

мұндағы 2 және 1 еркін және тізім y x тізімінен қысқарақ деп есептеледі.

0
қосылды
Бұл бір циклды және шартты пайдалануды қоспағанда, менің жеке іске асыруға ұқсас. Мен сенемін, сенің жақсы жұмыс өнімділігі жақсы болуы мүмкін
қосылды автор KingFu, көзі
sep, lst = 2, []
for i in range(len(y)+1):
    lst += x[i*sep:(i+1)*sep] + y[i:i+1]

элементі y элементінің алдында x элементтерінің саны келтірілген.

Өнімділік:

>>> timeit.timeit(stmt="for i in range(len(y)+1): lst += x[i*sep:(i+1)*sep] + y[i:i+1]", setup="lst = [];x = [1,2,3,4,5,6,7,8];y = ['a','b','c'];sep = 2", number=1000000)
2.8565280437469482

Өте жақсы нәрсе. let = [] дегеннен басталатын stmt кодын ала алмадым, сондықтан оны lst code> timeit ), бірақ әлі де ... миллион рет жақсы.

0
қосылды

itertools.izip_longest пайдалану:

>>> from itertools import izip_longest, chain
>>> y = ['a','b','c']
>>> x = [1,2,3,4,5,6,7,8]   
>>> lis = (x[i:i+2] for i in xrange(0, len(x) ,2)) # generator expression
>>> list(chain.from_iterable([ (a + [b]) if b else a  
                                            for a, b in izip_longest(lis, y)]))
[1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8]
0
қосылды
def merge(xs, ys):
    ys = iter(ys)
    for i, x in enumerate(xs, 1):
        yield x
        if i % 2 == 0:
            yield next(ys)

''.join(merge('12345678', 'abc')) # => '12a34b56c78'
0
қосылды