2015-07-29 4 views
8

Я пытаюсь создать функцию для смешивания двух списков в python, или я скорее скажу, что элемент list2 в list1. Необходимо, чтобы в списке вывода, не более чем два элемента рядом два друг с другом, имеют то же значениеСмешать два списка python

Например:

list1 = [1,1,1,1,1] 
list2 = [2,2,2,2,2] 
output = [1,1,2,1,2,2,1,2,1,2] 

Неправильный выход Пример:

# There are more than two '1' standing next two each other 
output = [1,1,1,2,2,1,2,1,2,2] 

Вот мой раствор:

def guyGenerator(toughGuy,softGuy): 
    i = 0 
    while len(softGuy) > 0: 
     temp = softGuy[:1] 
     while i < len(toughGuy) - 1: 
      if toughGuy[i] == toughGuy[i + 1] == 2: 
       toughGuy.insert(random.randint(i, i + 1), temp[0]) 
      i = i + 1 
     softGuy = softGuy[1:] 
    return toughGuy 

Вопрос заключается в получении выходных данных более чем с двумя одинаковыми элементами Энты стоя двух следующих друг с другом или длину списка вывода больше, чем совмещать длину двух списков

Например, один мой выход

[2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2] 

Что я здесь делаю неправильно?

Edit 1

Clodion спросил меня, так что я положил это здесь

Результаты могут быть случайными, если они удовлетворяют требованиям в этом вопросе. Порядок элементов не имеет значения, пока не более двух элементов, стоящих рядом друг с другом не имеют одинаковое значение

Edit 2

Я пытаюсь бездельничать по созданию Iterable класса, используя Clodion. Вот новый код:

import random 

class GuyGenerator: 
    def __init__(self,toughGuyList,softGuyList): 
     self.toughGuyList = toughGuyList 
     self.softGuyList = softGuyList 
    def __iter__(self): 
     return self 
    def __next__(self): 
     listSum = self.toughGuyList + self.softGuyList 
     while True: 
      res = random.sample(listSum,len(listSum)) 
      if not any([res[i-2]==res[i-1]==res[i] for i in range(len(listSum))]): 
       break 
     return res 

toughGuy = ['tough','tough','tough','tough','tough','tough','tough','tough'] 
softGuy = ['soft','soft','soft','soft','soft','soft','soft','soft'] 
for guy in GuyGenerator(toughGuy,softGuy): 
    print(guy) 

В результате получилось довольно хорошо, для кода, выполняющегося неограничен, за исключением, и я должен использовать KeyboardInterrupt, чтобы остановить код. Что я делаю неправильно в этом случае? Буду признателен с тщательным объяснением, так как я новичок в Python и итераторе

Редактировать 3

решена проблема итератора, проще, чем я думаю. Оказалось, что вернулся в ITER является то, что класс возврата при вызове в для цикла

Решение:

def __iter__(self):  
    listSum = self.listRandom1 + self.listRandom2 
    while True: 
     self.res = random.sample(listSum,len(listSum)) 
     if not any([self.res[i-2]==self.res[i-1]==self.res[i] for i in range(len(listSum))]): 
      break 
    return iter(self.res) 
+1

Что произойдет, если 'list's таковы, что нет никакого способа, чтобы расположить их так (например,' песни1 = [1,1,1]; песни2 = [1,1,1] ')? Каждый «список» всегда содержит один номер? – TigerhawkT3

+0

@Tuan Dinh: Можете ли вы сказать, хотите ли вы случайный результат или нет, пожалуйста? Заранее спасибо. И отредактируйте свой вопрос, чтобы написать его? – Clodion

+0

@Clodion: да, результат может быть случайным, если они удовлетворяют требованию –

ответ

6

Вы можете реализовать жадный алгоритм, который пытается получить наиболее распространенный предмет как можно чаще (то есть до двух раз), а затем при необходимости получить следующий наиболее распространенный элемент .

Это имеет два преимущества по сравнению с поиском по случайной перетасовки:

  • Жадный алгоритм намного быстрее, так как длина items увеличивается:

    In [223]: %timeit list(intermix([1]*10+[2]*5)) 
    10000 loops, best of 3: 39.8 µs per loop 
    
    In [222]: %timeit intermix_random([1]*10+[2]*5) 
    100 loops, best of 3: 6.85 ms per loop 
    
  • Он может определить, когда нет никакого решения , тогда как случайный поиск в случайном порядке петли навсегда, если посещенные тасования не кэшируются.


import collections 
def intermix(items, nconsecutive=2): 
    counter = collections.Counter(items) 
    # sort from most common to least common 
    items = sorted(items, key=counter.get, reverse=True) 
    N = len(items) 
    count = 0 
    # remember the last two values 
    last = [] 
    for i in range(N): 
     val = items[i] 
     if len(last) < nconsecutive: 
      if last and val == last[-1]: 
       last.append(val) 
      else: 
       last = [val] 
      counter[val] -= 1 
      yield val 
     else: 
      # last is full; find a different value 
      for j in range(i, N): 
       if items[j] != last[-1]: 
        items[i], items[j] = items[j], items[i] 
        val = items[i] 
        last = [val] 
        counter[val] -= 1 
        # as items are yielded, the meaning of "most common" can change. 
        items[i+1:] = sorted(items[i+1:], key=counter.get, reverse=True) 
        yield val 
        break 
      else: 
       raise ValueError('No solution possible') 

In [184]: list(intermix([1,1,1,1,1,2,2,2,2,2])) 
Out[184]: [1, 1, 2, 2, 1, 2, 2, 1, 2, 1] 

In [185]: list(intermix([1,0,1,1,2,1,0,1,1,1,2])) 
Out[185]: [1, 1, 0, 1, 1, 2, 1, 1, 2, 1, 0] 

In [186]: list(intermix([1,0,1,1,2,1,0,1,1,1,1,1,1,2])) 
Out[186]: [1, 1, 0, 1, 1, 2, 1, 1, 2, 1, 1, 0, 1, 1] 

In [187]: list(intermix([1,0,1,1,2,1,0,1,1,1,1,1,1,1,2])) 
ValueError: No solution possible 

In [188]: list(intermix([1,0,1,1,2,1,0,1,1,1,1,1,1,1,2], nconsecutive=3)) 
Out[188]: [1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0] 
+0

Ну, результат должен быть случайным ... Нет? – Clodion

+0

@Clodion - нет, я не вижу необходимости в случайном результате. Я не знаю, где вы это делаете. – TigerhawkT3

+0

@ TigerhawkT3: посмотрите мой ответ ниже моего кода. – Clodion

1

Вы можете использовать shuffle из random:

list1=[1,1,1,1,1] 
list2=[2,2,2,2,2] 
import random 
lst = list1+list2 
print(lst) 
while True: 
    random.shuffle(lst) 
    if not any([lst[i-2]==lst[i-1]==lst[i]for i in range(len(lst))]): 
     break 
print(lst) 

Результат:

[1, 2, 1, 1, 2, 1, 2, 2, 1, 2] 

Пояснение: Я добавляю два списка и suffle. Затем я повторяю shuffle, пока не будет 3 одинаковых последовательных номера. Как следует из комментариев, это может занять много времени, но легко сделать предел итераций.
Пытаясь объяснить, почему ваш код не работает:

def guyGenerator(toughGuy,softGuy): 
    import random 
    i = 0 
    while len(softGuy) > 0: 
     temp = softGuy[:1] 
     while i < len(toughGuy)- 1: 
      if toughGuy[i] == toughGuy[i + 1] == 2: 
       # you insert temp[0]: it can be inserted before i 
       # for lst = [0, 1, 2, 3] 
       # lst.insert(0, "X") result in ["X", 0, 1, 2, 3] 
       # But then, the next time, you'll test exactly the 
       # same thing: because you increment i and have move all 
       # the items of toughGuy one char to the right 
       # and that, without reducing softGuy len. 
       toughGuy.insert(random.randint(i, i + 1), temp[0]) 
      i = i + 1 
     softGuy = softGuy[1:] 
    return toughGuy 

print(guyGenerator([2,2,2,2,2], [1,1,1,1,1])) 

Ну? Я поняла?

lst = [1, 2, 3, 4, 5] 
>>> lst.insert(0, "X") 
>>> lst 
['X', 1, 2, 3, 4, 5] 
>>> lst = [1, 2, 3, 4, 5] 
>>> lst.insert(1, "X") 
>>> lst 
[1, 'X', 2, 3, 4, 5] 
>>> 

Если randint дать i, то "X", вставляется до пунктов.
Вы увеличиваете I и вы так я найти точно такой же элемент:

>>> lst = [1, 2, 3, 4, 5] 
>>> lst.insert(0, "X") 
>>> lst 
['X', 1, 2, 3, 4, 5] 
>>> lst.insert(1, "X") 
>>> lst 
['X', 'X', 1, 2, 3, 4, 5] 
>>> 

Это проблема, потому что вы все еще в том же цикле !!! Таким образом, вы можете вставить несколько темп [0], прежде чем уменьшать softGuy на один элемент. Да?
Любые предложения были бы приветствованы!

+0

Пожалуйста, почему этот «-1»? Заранее спасибо. – Clodion

+0

Я не знаю, почему «-1», но я тестирую ваше решение. Но можете ли вы сказать, что я делаю неправильно в своем решении? –

+7

Решение, основанное на случайности и которое теоретически может работать в течение нескольких часов, беспокоит меня, это лень, это не очень хороший способ кодирования. – Delgan

Смежные вопросы