如果元组的第一个项等于任何给定的字符串,则从列表中删除元组



我有一个列表如下:

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

我想从包含nvme1n1nvme0n1p1nvme0n1p128nvme0n1的列表中删除几个元组。

因此最终列表将具有

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

尝试如下,但没有工作&得到错误"AttributeError: 'tuple' object has no attribute 'startswith'"

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

有人能帮忙吗?

devices = [('nvme2n1',), ('nvme1n1', '/local'),
('nvme0n1',), ('nvme0n1p1', '/'), 
('nvme0n1p128',), ('nvme3n1',)]
devices = [device for device in devices if device[0] not in 
(("nvme0n1", "nvme0n1p1", "nvme0n1p128", "nvme0n1"))]
print(devices)

输出

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

@JamesCollefson在他们的回答中解决了代码中的特定问题以及如何解决它。这只是不同的,在我看来是实现您想要的更好/更干净的方式。

您甚至可以使用列表理解来简化它。正如James在回答中提到的,您需要执行word[0],因为word是元组而不是字符串。

startswith可以使用元组进行检查。

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

但如果你正在寻找精确的匹配,你可以,

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

您在devices列表中迭代的word是元组。您需要访问元组中您感兴趣的部分,如下所示:

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

@JamesRollefson的回答很好,触及了问题的核心。

顺便说一句,我只想补充一点,在处理列表和dict时,可以使用列表理解使代码更加简洁和优雅:

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

关于要衡量的标准究竟是什么,这个问题有点模糊。

例如,它必须是完全匹配、包含还是以开头。

以下是我提出的四个案例和解决方案的综合解决方案。

如果索引未知,还需要匹配元组中的任何内容。

如果你发现代码有任何问题/有建议,我会很乐意编辑。

还有未来的证明,所以应该避免使用要内联删除的项目列表,而不是将其设置为变量。因此,这种解决方案更为通用。

将以下内容与一起使用:final_device=remove_from_tuple_list(device,remove_list,0,match_type='contains'(

解决OP的具体问题。

代码用注释进行了充分注释。

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',)]
'''

最新更新