6
votes

Supprimer les tuples d'une liste si leurs premiers éléments sont égaux à l'une des chaînes données

J'ai une liste comme ci-dessous:

for word in devices[:]: 
    if word.startswith("nvme0n1","nvme0n1p1","nvme0n1p128"): 
        devices.remove(word)

Je veux supprimer quelques tuples de cette liste contenant nvme1n1 ou nvme0n1p1 ou nvme0n1p128 ou nvme0n1 .

donc la liste finale aura

final_device = [('nvme2n1',),('nvme3n1',)]

essayé comme ci-dessous mais n'a pas fonctionné et a obtenu l'erreur "AttributeError: 'tuple' object has no attribute 'startswith'"

device = [('nvme2n1',), 
          ('nvme1n1', '/local'), 
          ('nvme0n1',), 
          ('nvme0n1p1', '/'),
          ('nvme0n1p128',), 
          ('nvme3n1',)]

Quelqu'un peut-il aider avec ça?


1 commentaires

if word[0] == "nvme0n1" or word[0] == "nvme0n1p1" or word[0] == "nvme0n1p128"


5 Réponses :


5
votes

Les word vous parcourez dans la liste des devices sont des tuples. Vous devez accéder à la partie de ce tuple qui vous intéresse comme suit:

for word in devices[:]: 
    if word[0] in ["nvme0n1","nvme0n1p1","nvme0n1p128"]: 
        devices.remove(word)


5 commentaires

Belle réponse qui résout le problème. Il y a une faute de frappe, cependant, les devices[:] devraient simplement être des device . J'ai essayé de proposer une modification, mais les modifications doivent comporter au moins 6 caractères D =


Cela fonctionne comme je l'ai écrit, mais vous avez certainement raison de dire que c'est plus propre de cette façon. Merci @Asker. J'ai fait le changement que vous recommandiez.


@Asker @JamesTollefson le [:] est en fait nécessaire pour que cela fonctionne, sinon vous modifiez la liste en l'itérant, ce qui fera sauter certains éléments. Essayez-le avec les devices = [(1,), (2,), (3,), (4,)] et if word[0] in [1, 2, 3]: ... - la liste résultante est [(2,), (4,)] , ie (2,) n'est pas supprimé. Ce comportement est quelque peu décrit ici et ici .


@Czaporka Bon point, je n'ai pas pensé à ça! Désolé JamesTollefson pour la suggestion de modification erronée


Intéressant, @Czaporka, je n'en savais rien.



6
votes
[('nvme2n1',), ('nvme1n1', '/local'), ('nvme3n1',)]

0 commentaires

5
votes

Vous pouvez même utiliser une compréhension de liste pour le rendre plus simple. Comme James l'a mentionné dans sa réponse, vous devez faire le word[0] car le word est un tuple et non une chaîne.

startswith peut prendre un tuple pour vérifier.

[dev for dev in devices if dev[0] not in ("nvme0n1","nvme0n1p1","nvme0n1p128")]

Mais si vous recherchez des correspondances exactes, vous pouvez le faire,

[dev for dev in devices if not dev[0].startswith(("nvme0n1","nvme0n1p1","nvme0n1p128"))]


0 commentaires

2
votes

La réponse de @ JamesTollefson est agréable et va au cœur du problème.

En remarque, je voulais juste ajouter que lorsque vous traitez avec des listes et des dictionnaires, vous pouvez rendre votre code plus concis et élégant en utilisant des compréhensions de liste:

devices = [d in devices if d[0] not in {"nvme0n1", "nvme0n1p1", "nvme0n1p128", "nvme0n1"}]


0 commentaires

0
votes

La question est un peu vague de savoir exactement quels critères doivent être mesurés.

Par exemple, doit-il être une correspondance exacte, contenir ou commencer par.

Vous trouverez ci-dessous une solution complète que j'ai élaborée pour proposer quatre cas et solutions.

Il y a aussi l'élément supplémentaire de faire correspondre quoi que ce soit dans un tuple si l'index est inconnu.

Si vous rencontrez des problèmes avec le code / avez des suggestions, je serai ravi de le modifier.

Il y a aussi une épreuve future, donc utiliser la liste des éléments à supprimer en ligne et ne pas la définir sur une variable doit être évitée. Cette solution est donc plus générale.

Utilisation de ce qui suit avec: final_device = remove_from_tuple_list (device, remove_list, 0, match_type = 'contains')

Résout le problème spécifique du PO.

Le code est entièrement commenté avec des explications.

device = [('nvme2n1',), 
          ('nvme1n1', '/local'), 
          ('nvme0n1',),
          ('nvme0n1p1', '/'),
          ('nvme0n1p128',),
          ('nvme3n1',)]

remove_list = ['nvme1n1', 'nvme0n1p1' , 'nvme0n1p128', 'nvme0n1']

def analyze_item_criteria(item : str ,criteria : list,criteria_type : str):
    '''
    Check whether an item string or tuple is contained in a list of items

    Args:
        item : the item to be evaluated
        criteria : list of items to be checked against
        criteria_type: the type of criteria

    Returns:
        Boolean True/False if evaluated
        None if not evaluated
    
    Raises:
        'Invalid criteria_type specified' : if the item is not a valid criteria type

    '''
    ##Check that type is valid
    assert criteria_type in ['contains',
                          'exact',
                          'starts_with',
                          'ends_with',
                          ],'Invalid criteria_type specified'

    if criteria_type == 'exact':
        if item in criteria:
            return True
        else:
            return False
    ##Starts with/ends with also takes a tupe (.startswith((args,))) this implementation
    ##Isn't really different from what happens under the hood
    elif criteria_type == 'starts_with':
        if any([item.startswith(x) for x in criteria] ):
            return True
        else:
            return False
    elif criteria_type == 'ends_with':
        if any([item.endswith(x) for x in criteria] ):
            return True
        else:
            return False
    elif criteria_type == 'contains':
        if any([x in item for x in criteria]):
            return True
        else:
            return False
#Specifying no index does not really work with well exact but the other three options are still valid
def remove_from_tuple_list(tuple_list : list, remove_list :list, tuple_index : int = None, match_type : str = 'contains'):
    '''
    Function to remove items from a list of tuples containing specific words.
    The function can remove items at a specified index or any position if not specified

    Args:
        tuple_list : The list of tuples from which items are to be removed (items in tuple have to be str/int/float , objects will
                      have unexpected behaviour)
        remove_list : list of strings/items to be removed from the tuple_list
        tuple_index : if an integer, checks for criteria at the specific position otherwise the whole tuple which is inefficient
                      Set to none if you want to analyze a list of strings for example as well
        match_type : Do we want to match the word exactly or do we look for it containing the word
                      There are a few cases to consider here.
                      - contains
                      - exact
                      - starts_with
                      - ends_with
    Returns:
        list of items not in remove_list

    Raises:
        'Invalid match_type specified' : if the item is not in the match list
    '''

    ##Check that type is valid
    assert match_type in ['contains', 
                          'exact',
                          'starts_with',
                          'ends_with',
                          ],'Invalid match_type specified'
    new_tuple_list = []
    #Check whether we are looking at a specific index in the tuple

    ##This can be done multiple ways, think analysing the if once is the most efficient so justifies the additional typing
    if isinstance(tuple_index,int):
        new_tuple_list = [
                            list_item for list_item in tuple_list 
                            if not analyze_item_criteria(list_item[tuple_index],remove_list,match_type)
                        ]
    else:
        new_tuple_list = [list_item for list_item in tuple_list if not analyze_item_criteria('|'.join([str(x) for x in list_item])
        ,remove_list,match_type)]

    return new_tuple_list





def test():
    final_device = remove_from_tuple_list(device,remove_list,0,match_type = 'contains')
    print(remove_from_tuple_list(device,remove_list,0,match_type = 'contains'))
    print(remove_from_tuple_list(device,remove_list,0,match_type = 'exact'))
    remove_list = ['nvme1n1', 'nvme0n1p1', 'nvme0n1']
    print(remove_from_tuple_list(device,remove_list,0,match_type = 'ends_with'))
    print(remove_from_tuple_list(device,remove_list,0,match_type = 'starts_with'))


    print(remove_from_tuple_list(device,remove_list,None,match_type = 'contains'))
    print(remove_from_tuple_list(device,remove_list,None,match_type = 'exact'))
    remove_list = ['nvme1n1', 'nvme0n1p1', 'nvme0n1']
    print(remove_from_tuple_list(device,remove_list,None,match_type = 'ends_with'))
    print(remove_from_tuple_list(device,remove_list,None,match_type = 'starts_with'))

    '''
    Output:
    -------
    [('nvme2n1',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme0n1p128',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme1n1', '/local'), ('nvme0n1p1', '/'), ('nvme0n1p128',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme1n1', '/local'), ('nvme0n1p1', '/'), ('nvme0n1p128',), ('nvme3n1',)]
    [('nvme2n1',), ('nvme3n1',)]
    '''


0 commentaires