2015-11-26 10 views
0

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

1 2 3 4 o o o 5 6 7 

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

5 6 7 1 2 3 4 o o o 

Проблема в том, что o может быть также смежным циклическим способом. Например,

o o 1 2 3 4 5 6 7 o 

Есть ли разумный способ сделать это? Я смотрел на cycle из itertools, но на данный момент у меня нет рабочей реализации, поскольку то, что я сделал, не может справиться с последним случаем.

ОБНОВЛЕНИЕ

У меня есть первый рабочий реализации:

def arrange2(nodes, contiguous): 

    arranged = [] 
    size = len(nodes) 

    if nodes[0] in contiguous: 

     # obtain the id of the last interface node in nodes 
     id = None 
     for i in range(1, len(nodes)): 
      if nodes[i] not in contiguous: 
       id = i 
       break 

     # copy nodes to new list starting from the first node past id 
     for i in range(id, id + size): 
      arranged += [nodes[i % size]] 
    else: 

     # obtain the id of the last interface node in nodes 
     id = None 
     for i in range(size - 1, -1, -1): 
      if nodes[i] in contiguous: 
       id = i 
       break 

     # copy nodes to new list starting from the first node past id 
     for i in range(id+1, id + size+1): 
      arranged += [nodes[i % size]] 

    return arranged 


print(arrange2([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [5, 6])) 

Это печатает [7, 8, 9, 10, 1, 2, 3, 4, 5, 6]

+1

могли бы вы предоставить более реальные примеры? Я не понимаю, почему смежный должен быть '[5,6]', а не только 6. – Mel

+0

Вы можете взять любой набор смежных чисел из этого списка.Я взял '[5,6]' в качестве примера, но вы могли бы взять '[9, 10, 1, 2]', который является непрерывным циклическим способом, или '[10, 1, 2]' и т. Д. – aaragon

+0

Но какая разница между «Я хочу 2 в конце» и «Я хочу 10,1,2» в конце? Если вы положите 2 в конце и сохраните заказ, тогда у вас будет «10,1,2» в конце. – Mel

ответ

1

Ok, основываясь на вас реализации у меня есть это:

def arrange(nodes: list, contigious: list) -> list: 
    first_contigious = nodes.index(contigious[0]) 
    last_contigious = nodes.index(contigious[-1]) 

    if first_contigious < last_contigious: 
     # Normal situation 
     return nodes[last_contigious+1:] + nodes[:first_contigious] + contigious 
    else: 
     # The contigious part is cycling 
     return nodes[last_contigious+1:first_contigious] + contigious 

EDIT, после разъяснения в комментариях, что contigious сбор не должен быть заказан у меня есть это:

def arrange(nodes: list, contigious: set) -> list: 
    # Make sure that contigious is a set 
    contigious = set(contigious) 

    # Return if all nodes are in contigious or nodes are empty 
    if len(contigious.intersection(nodes)) == len(nodes) or not len(nodes): 
     return nodes 

    if nodes[0] in contigious and nodes[-1] in contigious: 
     # The contigious part is split and present on the beggining and the 
     # end of the nodes list 
     cut = next(i for i, x in enumerate(nodes) if x not in contigious) 
     # I move the nodes from the beggining to the end 
     return nodes[cut:] + nodes[:cut] 
    else: 
     # The contigious part is somewhere in the middle of the nodes list 
     # I need to find the end of contigious sequence 
     cut = next(i for i, x in enumerate(reversed(nodes)) if x in contigious) 
     cut = len(nodes) - cut 
     return nodes[cut:] + nodes[:cut] 

Примечание: Это ваша работа, чтобы убедиться, что contigious элементы действительно рядом друг друга и не разбросаны в 3 или более группах.

+0

Это не работает – aaragon

+1

Пожалуйста, разместите встречный пример, чтобы я мог его исправить. – Maciek

+0

Это не удается: 'print (аранжировать ([400, 259, 260, 401], [400, 401]))' – aaragon

1

Используя тот факт, что все «о» непрерывны, я реализовал:

def rearrange(l): 
    i=0 
    found=False 
    while i<len(l): 
     if l[i]=="o": 
      found=True 
      l=l[i+1:]+l[:i+1] 
      i=0 
     else: 
      if found: 
       break 
      i+=1 
    return l 

Вы итерацию по списку. В первом случае i «o» вы разбиваете список и инвертируете его. l=["o","o",1,2,3,"o"] «раскол» в ["o"] (l[:i+1]) и ["o",1,2,3,"o"] (l[i+1:]). Переверните две части и верните их вместе, вы получите новый список ["o",1,2,3,"o","o"].
Таким образом, «o» выдвигаются до конца.

Затем вы начинаете с нового списка. Когда новый список не начинается с 'o' (found - True и l[i]!="o"), это означает, что вы сделали.

>>>l=[1,2,3,4,"o","o","o",5,6,7] 
>>>print(rearrange(l)) 
[5, 6, 7, 1, 2, 3, 4, 'o', 'o', 'o'] 


>>>l=["o","o",1,2,3,"o"] 
>>>print(rearrange(l)) 
[1, 2, 3, 'o', 'o', 'o'] 

Чтобы предоставить список смежного элемента вместо «о», это небольшое изменение должно работать:

def rearrange(l,contiguous): 
    i=0 
    found=False 
    while i<len(l): 
     if l[i] in contiguous: 
      ... 
+0

Но, глядя на то, что вы обновляете, я предполагаю, что я взял «о» немного слишком буквально. – Mel

+0

Есть ли менее верный способ сделать это? Кроме того, посмотрите на пример, который я дал, у меня есть список значений, которые смежны, тогда как вы проверяете только «o». – aaragon

+0

Да, похоже, это работает. Пока что лучший ответ. – aaragon

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

  • Нет связанных вопросов^_^