Indexer tout * sauf * un élément en python


113

Existe-t-il un moyen simple d'indexer tous les éléments d'une liste (ou d'un tableau, ou autre) à l' exception d'un index particulier? Par exemple,

  • mylist[3] renverra l'article en position 3

  • milist[~3] renverra la liste entière sauf pour 3

Réponses:


112

Pour une liste , vous pouvez utiliser une liste comp. Par exemple, pour faire bune copie de asans le 3ème élément:

a = range(10)[::-1]                       # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
b = [x for i,x in enumerate(a) if i!=3]   # [9, 8, 7, 5, 4, 3, 2, 1, 0]

Ceci est très général et peut être utilisé avec tous les itérables, y compris les tableaux numpy. Si vous remplacez []par (), bsera un itérateur au lieu d'une liste.

Ou vous pouvez le faire sur place avec pop:

a = range(10)[::-1]     # a = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
a.pop(3)                # a = [9, 8, 7, 5, 4, 3, 2, 1, 0]

Dans numpy, vous pouvez le faire avec une indexation booléenne:

a = np.arange(9, -1, -1)     # a = array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
b = a[np.arange(len(a))!=3]  # b = array([9, 8, 7, 5, 4, 3, 2, 1, 0])

ce qui sera, en général, beaucoup plus rapide que la compréhension de la liste ci-dessus.


52
>>> l = range(1,10)
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[:2] 
[1, 2]
>>> l[3:]
[4, 5, 6, 7, 8, 9]
>>> l[:2] + l[3:]
[1, 2, 4, 5, 6, 7, 8, 9]
>>> 

Voir également

Expliquer la notation de tranche de Python


2
Bonne réponse pour une liste. Vous pouvez également l'utiliser pour les tableaux, mais vous devrez l'utiliser numpy.concatenate.
Bi Rico

48

Le moyen le plus simple que j'ai trouvé était:

mylist[:x]+mylist[x+1:]

cela produira votre mylistsans l'élément à l'index x.


J'ai trouvé que cela supprimait l'élément x + 1, toujours utile, merci
Jack TC

24

Si vous utilisez numpy, le plus proche auquel je puisse penser est d'utiliser un masque

>>> import numpy as np
>>> arr = np.arange(1,10)
>>> mask = np.ones(arr.shape,dtype=bool)
>>> mask[5]=0
>>> arr[mask]
array([1, 2, 3, 4, 5, 7, 8, 9])

Quelque chose de similaire peut être réalisé en utilisant itertoolssansnumpy

>>> from itertools import compress
>>> arr = range(1,10)
>>> mask = [1]*len(arr)
>>> mask[5]=0
>>> list(compress(arr,mask))
[1, 2, 3, 4, 5, 7, 8, 9]

2
Je pourrais utiliser quelque chose comme np.arange(len(arr)) != 3le masque, car alors il peut être incorporé, par exemple arr[~(np.arange(len(arr)) == 3)]ou autre.
DSM

@DSM: Veuillez poster ceci comme réponse :-). Quoi qu'il en soit, je ne suis pas tout à fait familier avec Numpy.
Abhijit

+1 pour masquer un tableau, dans le cas d'une liste, j'irais avec slice et concaténerais en utilisant compress.
Bi Rico

5

Utilisez np.delete! Il ne supprime en fait rien en place

Exemple:

import numpy as np
a = np.array([[1,4],[5,7],[3,1]])                                       

# a: array([[1, 4],
#           [5, 7],
#           [3, 1]])

ind = np.array([0,1])                                                   

# ind: array([0, 1])

# a[ind]: array([[1, 4],
#                [5, 7]])

all_except_index = np.delete(a, ind, axis=0)                                              
# all_except_index: array([[3, 1]])

# a: (still the same): array([[1, 4],
#                             [5, 7],
#                             [3, 1]])

2

Je vais fournir une manière fonctionnelle (immuable) de le faire.

  1. Le moyen standard et simple de le faire est d'utiliser le tranchage:

    index_to_remove = 3
    data = [*range(5)]
    new_data = data[:index_to_remove] + data[index_to_remove + 1:]
    
    print(f"data: {data}, new_data: {new_data}")

    Production:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  2. Utilisez la compréhension de liste:

    data = [*range(5)]
    new_data = [v for i, v in enumerate(data) if i != index_to_remove]
    
    print(f"data: {data}, new_data: {new_data}") 

    Production:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  3. Utilisez la fonction de filtre:

    index_to_remove = 3
    data = [*range(5)]
    new_data = [*filter(lambda i: i != index_to_remove, data)]

    Production:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  4. Utiliser le masquage. Le masquage est fourni par la fonction itertools.compress dans la bibliothèque standard:

    from itertools import compress
    
    index_to_remove = 3
    data = [*range(5)]
    mask = [1] * len(data)
    mask[index_to_remove] = 0
    new_data = [*compress(data, mask)]
    
    print(f"data: {data}, mask: {mask}, new_data: {new_data}")

    Production:

    data: [0, 1, 2, 3, 4], mask: [1, 1, 1, 0, 1], new_data: [0, 1, 2, 4]
  5. Utilisez la fonction itertools.filterfalse de la bibliothèque standard Python

    from itertools import filterfalse
    
    index_to_remove = 3
    data = [*range(5)]
    new_data = [*filterfalse(lambda i: i == index_to_remove, data)]
    
    print(f"data: {data}, new_data: {new_data}")

    Production:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]

0

Si vous ne connaissez pas l'index à l'avance, voici une fonction qui fonctionnera

def reverse_index(l, index):
    try:
        l.pop(index)
        return l
    except IndexError:
        return False

0

Notez que si la variable est une liste de listes, certaines approches échoueraient. Par exemple:

v1 = [[range(3)] for x in range(4)]
v2 = v1[:3]+v1[4:] # this fails
v2

Pour le cas général, utilisez

removed_index = 1
v1 = [[range(3)] for x in range(4)]
v2 = [x for i,x in enumerate(v1) if x!=removed_index]
v2

0

Si vous souhaitez supprimer le dernier ou le premier, procédez comme suit:

list = ["This", "is", "a", "list"]
listnolast = list[:-1]
listnofirst = list[1:]

Si vous changez 1 en 2, les 2 premiers caractères seront supprimés et non le second. J'espère que cela aide encore!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.