按字典中的值过滤项目
filter items by value in dict
我的字典设置如下:
deck = [{
'name': 'drew',
'lvl': 23,
'items': ['sword', 'axe', 'mana_potion']},
{
'name': 'john',
'lvl': 23,
'items': ['sword', 'mace', 'health_potion']}]
这是一个基本示例,我需要一种方法来过滤(仅复制{characters})匹配特定值的字符,例如我只想要 23 级的字符,或者携带一把剑。
我正在考虑做这样的事情:
filtered = filter_deck(deck, 'mace')
def filter_deck(self, deck, filt):
return [{k:v for (k,v) in deck.items() if filt in k}]
和return:
filtered = [{
'name': 'john',
'lvl': 23,
'items': ['sword', 'mace', 'health_potion']}]
我不确定如何过滤特定项目,例如 k:v 或 k:[v1,v2,v3],因为我不知道它是单个值还是值列表,或者如何过滤多个值。
我不确定如何使用多个键来过滤字符。假设我想整理出 23 级的角色,或者有物品 ['sword'] 或物品 ['mace'] 的角色。我将如何以 filter_cards(deck, ['lvl'=23, 'items'=['sword','mace'])
的方式对其进行排序
所以如果任何角色是 23 级,或者携带狼牙棒或剑,他们就会在该列表中。
您的 deck
是一个列表(字典),它没有 .items()
。所以尝试这样做 - deck.items()
会失败。
还有语法 -
filter_cards(deck, ['lvl'=23, 'items'=['sword','mace'])
无效,你应该使用字典作为第二个元素。示例 -
filter_cards(deck, {'lvl':23, 'items':['sword','mace']})
您应该使用 filter()
内置函数,如果字典包含其中一个值,则函数 returns 为真。示例 -
def filter_func(dic, filterdic):
for k,v in filterdic.items():
if k == 'items':
if any(elemv in dic[k] for elemv in v):
return True
elif v == dic[k]:
return True
return False
def filter_cards(deck, filterdic):
return list(filter(lambda dic, filterdic=filterdic: filter_func(dic, filterdic) , deck))
演示 -
>>> deck = [{
... 'name': 'drew',
... 'lvl': 23,
... 'items': ['sword', 'axe', 'mana_potion']},{
... 'name': 'john',
... 'lvl': 23,
... 'items': ['sword', 'mace', 'health_potion']},{
... 'name': 'somethingelse',
... 'lvl': 10,
... 'items': ['health_potion']}]
>>>
>>>
>>> filter_cards(deck, {'lvl':23, 'items':['sword','mace']})
[{'lvl': 23, 'items': ['sword', 'axe', 'mana_potion'], 'name': 'drew'}, {'lvl': 23, 'items': ['sword', 'mace', 'health_potion'], 'name': 'john'}]
您可以只使用标准 filter
并传入过滤函数,例如:
filter(lambda x: 'mace' in x['items'], deck)
filter(lambda x: x['lvl'] == 23 or any(i in x['items'] for i in ['sword', 'mace']), deck)
等这些 return 个过滤器生成器,所以如果你想将它们打印出来,请将它们变成一个列表:
>>> list(filter(lambda x: x['lvl'] == 23 or any(i in x['items'] for i in ['sword', 'mace']), deck))
[{'items': ['sword', 'axe', 'mana_potion'], 'lvl': 23, 'name': 'drew'},
{'items': ['sword', 'mace', 'health_potion'], 'lvl': 23, 'name': 'john'}]
您也可以将 lambda 分解为标准函数:
>>> def lvl_sword_mace(x):
... return x['lvl'] == 23 or any(i in x['items'] for i in ['sword', 'mace'])
...
>>> list(filter(lvl_sword_mace, deck))
[{'items': ['sword', 'axe', 'mana_potion'], 'lvl': 23, 'name': 'drew'},
{'items': ['sword', 'mace', 'health_potion'], 'lvl': 23, 'name': 'john'}]
使用列表理解过滤字典的正确方法是请求要过滤的字段。 key in dictionary
等同于 python2 中的 key in dictionary.keys()
。正确的语法如下:
[card for card in deck if 'mace' in card['items']]
你也可以使用filter
:
filter(lambda card: 'mace' in card['items'], deck)
如果您想过滤多个值,您可以使用 and
和 or
链接测试来捕获您需要的子集:
[card for card in deck if 'mace' in card['items'] and card['lvl'] == 23]
如果过滤器变大,请创建一个函数。
在这种情况下,filter
没有提供比列表压缩更多的价值。 列表理解 比 filter
对应部分更简短,更易于阅读。对于复杂的 filtering 情况,两者都需要一个函数来保持可读性。
deck
不是字典,而是字典列表,因此我认为您的搜索应该 return 符合搜索条件的字典列表。
有两种情况需要考虑:第一种是当您想要为特定键匹配特定值时 - 对于 lvl
和 name
等属性,您将需要这种情况。第二个是您要在针对属性存储的列表中查找值的位置。例如,您将需要它来查明玩家是否携带了特定物品。
你实际上 知道 它们之间的区别是有意义的 - 大概 items
总是一个列表,而 lvl
总是一个整数? - 你可以像这样在附属字典中注册类型:
is_list = {'name': False,
'lvl': False,
'items': True}
如果必须通过检查项目的 type()
,您可以动态地做出相同的决定,但是使用可变数据类型并不是很好的做法,因为它会使您的逻辑变得有些复杂。由于您向函数添加了一个 self
参数,我认为它是一种方法,但这与问题并不相关。
鉴于 is_list
的存在,您的逻辑可以定义一个 test_card
函数,如果卡片满足您的条件,该函数 return 为真,以及一个迭代的 filter_deck
函数在一副牌中 return 只收集至少满足其中一项条件的卡片。然后逻辑看起来像这样:
deck = [{
'name': 'drew',
'lvl': 23,
'items': ['sword', 'axe', 'mana_potion']},
{'name': 'john',
'lvl': 23,
'items': ['sword', 'mace', 'health_potion']},
{'name': 'somethingelse',
'lvl': 10,
'items': ['health_potion']}]
is_list = {'name': False,
'lvl': False,
'items': True}
def test_card(card, name, values):
if is_list[name]: # values is a list
return any(value in card[name] for value in values)
else: # values is a single value
return card[name] == values
def filter_deck(deck, **filters): # filters is a dict of keyword args
r = []
for d in deck:
#print "Filtering", d, "on", filters
if any(test_card(d, n, v) for n, v in filters.items()):
r.append(d)
return r
print filter_deck(deck, name="john")
print filter_deck(deck, name="drew", lvl=10)
输出
[{'lvl': 23, 'name': 'john', 'items': ['sword', 'mace', 'health_potion']}]
[{'lvl': 23, 'name': 'drew', 'items': ['sword', 'axe', 'mana_potion']}, {'lvl': 10, 'name': 'somethingelse', 'items': ['health_potion']}]
您可以通过在 filter_deck
中使用列表理解来进一步压缩逻辑,但这可能会使程序更难以阅读和理解。我总是首先尝试可读性。
我的字典设置如下:
deck = [{
'name': 'drew',
'lvl': 23,
'items': ['sword', 'axe', 'mana_potion']},
{
'name': 'john',
'lvl': 23,
'items': ['sword', 'mace', 'health_potion']}]
这是一个基本示例,我需要一种方法来过滤(仅复制{characters})匹配特定值的字符,例如我只想要 23 级的字符,或者携带一把剑。
我正在考虑做这样的事情:
filtered = filter_deck(deck, 'mace')
def filter_deck(self, deck, filt):
return [{k:v for (k,v) in deck.items() if filt in k}]
和return:
filtered = [{
'name': 'john',
'lvl': 23,
'items': ['sword', 'mace', 'health_potion']}]
我不确定如何过滤特定项目,例如 k:v 或 k:[v1,v2,v3],因为我不知道它是单个值还是值列表,或者如何过滤多个值。
我不确定如何使用多个键来过滤字符。假设我想整理出 23 级的角色,或者有物品 ['sword'] 或物品 ['mace'] 的角色。我将如何以 filter_cards(deck, ['lvl'=23, 'items'=['sword','mace'])
所以如果任何角色是 23 级,或者携带狼牙棒或剑,他们就会在该列表中。
您的 deck
是一个列表(字典),它没有 .items()
。所以尝试这样做 - deck.items()
会失败。
还有语法 -
filter_cards(deck, ['lvl'=23, 'items'=['sword','mace'])
无效,你应该使用字典作为第二个元素。示例 -
filter_cards(deck, {'lvl':23, 'items':['sword','mace']})
您应该使用 filter()
内置函数,如果字典包含其中一个值,则函数 returns 为真。示例 -
def filter_func(dic, filterdic):
for k,v in filterdic.items():
if k == 'items':
if any(elemv in dic[k] for elemv in v):
return True
elif v == dic[k]:
return True
return False
def filter_cards(deck, filterdic):
return list(filter(lambda dic, filterdic=filterdic: filter_func(dic, filterdic) , deck))
演示 -
>>> deck = [{
... 'name': 'drew',
... 'lvl': 23,
... 'items': ['sword', 'axe', 'mana_potion']},{
... 'name': 'john',
... 'lvl': 23,
... 'items': ['sword', 'mace', 'health_potion']},{
... 'name': 'somethingelse',
... 'lvl': 10,
... 'items': ['health_potion']}]
>>>
>>>
>>> filter_cards(deck, {'lvl':23, 'items':['sword','mace']})
[{'lvl': 23, 'items': ['sword', 'axe', 'mana_potion'], 'name': 'drew'}, {'lvl': 23, 'items': ['sword', 'mace', 'health_potion'], 'name': 'john'}]
您可以只使用标准 filter
并传入过滤函数,例如:
filter(lambda x: 'mace' in x['items'], deck)
filter(lambda x: x['lvl'] == 23 or any(i in x['items'] for i in ['sword', 'mace']), deck)
等这些 return 个过滤器生成器,所以如果你想将它们打印出来,请将它们变成一个列表:
>>> list(filter(lambda x: x['lvl'] == 23 or any(i in x['items'] for i in ['sword', 'mace']), deck))
[{'items': ['sword', 'axe', 'mana_potion'], 'lvl': 23, 'name': 'drew'},
{'items': ['sword', 'mace', 'health_potion'], 'lvl': 23, 'name': 'john'}]
您也可以将 lambda 分解为标准函数:
>>> def lvl_sword_mace(x):
... return x['lvl'] == 23 or any(i in x['items'] for i in ['sword', 'mace'])
...
>>> list(filter(lvl_sword_mace, deck))
[{'items': ['sword', 'axe', 'mana_potion'], 'lvl': 23, 'name': 'drew'},
{'items': ['sword', 'mace', 'health_potion'], 'lvl': 23, 'name': 'john'}]
使用列表理解过滤字典的正确方法是请求要过滤的字段。 key in dictionary
等同于 python2 中的 key in dictionary.keys()
。正确的语法如下:
[card for card in deck if 'mace' in card['items']]
你也可以使用filter
:
filter(lambda card: 'mace' in card['items'], deck)
如果您想过滤多个值,您可以使用 and
和 or
链接测试来捕获您需要的子集:
[card for card in deck if 'mace' in card['items'] and card['lvl'] == 23]
如果过滤器变大,请创建一个函数。
在这种情况下,filter
没有提供比列表压缩更多的价值。 列表理解 比 filter
对应部分更简短,更易于阅读。对于复杂的 filtering 情况,两者都需要一个函数来保持可读性。
deck
不是字典,而是字典列表,因此我认为您的搜索应该 return 符合搜索条件的字典列表。
有两种情况需要考虑:第一种是当您想要为特定键匹配特定值时 - 对于 lvl
和 name
等属性,您将需要这种情况。第二个是您要在针对属性存储的列表中查找值的位置。例如,您将需要它来查明玩家是否携带了特定物品。
你实际上 知道 它们之间的区别是有意义的 - 大概 items
总是一个列表,而 lvl
总是一个整数? - 你可以像这样在附属字典中注册类型:
is_list = {'name': False,
'lvl': False,
'items': True}
如果必须通过检查项目的 type()
,您可以动态地做出相同的决定,但是使用可变数据类型并不是很好的做法,因为它会使您的逻辑变得有些复杂。由于您向函数添加了一个 self
参数,我认为它是一种方法,但这与问题并不相关。
鉴于 is_list
的存在,您的逻辑可以定义一个 test_card
函数,如果卡片满足您的条件,该函数 return 为真,以及一个迭代的 filter_deck
函数在一副牌中 return 只收集至少满足其中一项条件的卡片。然后逻辑看起来像这样:
deck = [{
'name': 'drew',
'lvl': 23,
'items': ['sword', 'axe', 'mana_potion']},
{'name': 'john',
'lvl': 23,
'items': ['sword', 'mace', 'health_potion']},
{'name': 'somethingelse',
'lvl': 10,
'items': ['health_potion']}]
is_list = {'name': False,
'lvl': False,
'items': True}
def test_card(card, name, values):
if is_list[name]: # values is a list
return any(value in card[name] for value in values)
else: # values is a single value
return card[name] == values
def filter_deck(deck, **filters): # filters is a dict of keyword args
r = []
for d in deck:
#print "Filtering", d, "on", filters
if any(test_card(d, n, v) for n, v in filters.items()):
r.append(d)
return r
print filter_deck(deck, name="john")
print filter_deck(deck, name="drew", lvl=10)
输出
[{'lvl': 23, 'name': 'john', 'items': ['sword', 'mace', 'health_potion']}]
[{'lvl': 23, 'name': 'drew', 'items': ['sword', 'axe', 'mana_potion']}, {'lvl': 10, 'name': 'somethingelse', 'items': ['health_potion']}]
您可以通过在 filter_deck
中使用列表理解来进一步压缩逻辑,但这可能会使程序更难以阅读和理解。我总是首先尝试可读性。