3
votes

inverser les séquences ascendantes dans une liste

Essayer de comprendre comment inverser plusieurs séquences ascendantes dans une liste.

Par exemple: input = [1,2,2,3] à output = [2,1,3,2] .

J'ai utilisé mylist.reverse () mais bien sûr cela revient à [3,2,2,1] . Vous ne savez pas quelle approche adopter?

Exemple en détail:

Disons donc que [5, 7, 10, 2, 7, 8, 1, 3] est l'entrée - la sortie doit être [10,7,5,8, 7,2,3,1] . Dans cet exemple, les 3 premiers éléments 5,7,10 sont dans l'ordre croissant, 2,7,8 est également dans l'ordre croissant et 1,3 également dans l'ordre croissant. La fonction devrait être capable de reconnaître ce modèle et d'inverser chaque séquence et de renvoyer une nouvelle liste.


2 commentaires

Pouvez-vous augmenter le nombre d'éléments dans la liste et afficher à nouveau le résultat souhaité? Ce n'est pas possible de comprendre ce que vous voulez, il peut y avoir plus de cas.


" Vous ne savez pas quelle approche adopter? " - combien d'approches avez-vous proposées et qu'est-ce qui rend difficile le choix entre elles? Ce sont des devoirs, probablement toute approche qui fonctionne sera assez bonne ..? Ceci est un site QA, posez une question qui VOUS aidera à progresser dans sa résolution - le simple fait de larguer "J'ai besoin de code pour faire X" n'est pas une bonne question.


5 Réponses :


1
votes

Tout ce dont vous avez besoin est de trouver toutes les sous-séquences non décroissantes et de les inverser:

In [47]: l = [5, 7, 10, 2, 7, 8, 1, 3]    

In [48]: res = []

In [49]: start_idx = 0

In [50]: for idx in range(max(len(l) - 1, 0)):
    ...:     if l[idx] >= l[idx - 1]:
    ...:         continue
    ...:     step = l[start_idx:idx]
    ...:     step.reverse()
    ...:     res.extend(step)
    ...:     start_idx = idx
    ...:

In [51]: step = l[start_idx:]

In [52]: step.reverse()

In [53]: res.extend(step)

In [54]: print(res)
[10, 7, 5, 8, 7, 2, 3, 1]

Pour augmenter les sous-séquences, vous devez changer si l [idx]> = l [idx - 1] à si l [idx]> l [idx - 1]


0 commentaires

1
votes

Il existe probablement une manière plus élégante de le faire, mais une approche consisterait à utiliser itertools.zip_longest avec enumerate pour parcourir des paires d'éléments séquentiels dans votre liste et garder une trace de chaque index où la séquence n'est plus croissant ou la liste est épuisée afin de découper, inverser et étendre votre liste de sortie avec les éléments découpés.

from itertools import zip_longest

d = [5, 7, 10, 2, 7, 8, 1, 3]

results = []
stop = None
for i, (a, b) in enumerate(zip_longest(d, d[1:])):
    if not b or b <= a:
        results.extend(d[i:stop:-1])
        stop = i

print(results)
# [10, 7, 5, 8, 7, 2, 3, 1]


0 commentaires

1
votes

Parcourez la liste en créant une fenêtre de plus en plus grande entre les positions x et y. Lorsque vous trouvez un endroit où le numéro suivant n'est pas croissant ou que vous atteignez la fin, coupez en sens inverse la fenêtre que vous venez de couvrir et ajoutez-la à la fin d'une liste de sortie:

data = [5, 7, 10, 2, 7, 8, 1, 3]
output = []

x = None
for y in range(len(data)):
  if y == len(data) - 1 or data[y] >= data[y+1]:
    output.extend(data[y:x:-1])
    x = y

print(output)


0 commentaires

0
votes
data = [5, 7, 10, 2, 7, 8, 1, 3,2]
def func(data):
    result =[]
    temp =[]
    data.append(data[-1])
    for i in range(1,len(data)):
        if data[i]>=data[i-1]:
            temp.append(data[i-1])
        else:
            temp.append(data[i-1])
            temp.reverse()
            result.extend(temp)
            temp=[]
    if len(temp)!=0:
        temp.reverse()
        result.extend(temp)
    temp.clear()
    return result

print(func(data))

# output [10, 7, 5, 8, 7, 2, 3, 1, 2] 

0 commentaires

0
votes

Vous pouvez définir une méthode pratique générale qui renvoie des tranches d'un tableau en fonction de la condition (prédicat).

res = []
for e in slice_when(lambda x,y: x > y, array):
  res.extend(e[::-1] )

res #=> [10, 7, 5, 8, 7, 2, 3, 1]


Maintenant, la tranche doit être faite lorsque l'élément suivant est plus petit que le précédent, par exemple:

array = [5, 7, 10, 2, 7, 8, 1, 3]
slices = slice_when(lambda x,y: x > y, array)
print(list(slices))
#=> [[5, 7, 10], [2, 7, 8], [1, 3]]

Vous pouvez donc l'utiliser aussi simple que: p>

def slice_when(predicate, iterable):
  i, x, size = 0, 0, len(iterable)
  while i < size-1:
    if predicate(iterable[i], iterable[i+1]):
      yield iterable[x:i+1] 
      x = i + 1
    i += 1
  yield iterable[x:size] 


0 commentaires