我有一本字典,我想用另外一本字典过滤(这个帖子中间显示的“过滤选项”)有多个项目。我可以为单个项目而不是整个字典找出一些东西...我已经看了一段时间,但其他答案只针对一个条目的过滤器(很好地解决了字典理解)
这是我到目前为止单项词典过滤器所做的工作,即
filter_options = {
'Attack': 25}
for kfo, vfo in filter_options.iteritems():
for kp, vp in pokers.iteritems():
if vp[kfo] >= vfo:
print pokedex[kp]
它有效,但我无法弄清楚过滤多个项目
这是字典的截断版本
pokedex = {1: {'Attack': 49.0,
'Defense': 49.0,
'HP': 45.0,
'Name': 'Bulbasaur',
'PokedexNumber': 1.0,
'SpecialAttack': 65.0,
'SpecialDefense': 65.0,
'Speed': 45.0,
'Total': 318.0,
'Type': 'GrassPoison'},
2: {'Attack': 62.0,
'Defense': 63.0,
'HP': 60.0,
'Name': 'Ivysaur',
'PokedexNumber': 2.0,
'SpecialAttack': 80.0,
'SpecialDefense': 80.0,
'Speed': 60.0,
'Total': 405.0,
'Type': 'GrassPoison'},
3: {'Attack': 82.0,
'Defense': 83.0,
'HP': 80.0,
'Name': 'Venusaur',
'PokedexNumber': 3.0,
'SpecialAttack': 100.0,
'SpecialDefense': 100.0,
'Speed': 80.0,
'Total': 525.0,
'Type': 'GrassPoison'}}
# Only filter based on parameters passed
filter_options = {
'Attack': 25,
'Defense': 30,
'Type': 'Electric'
}
即返回记录攻击> = 25,防御> = 30,并输入==“电” 还预计其他参数也可以通过,如“SpecialAttack”,“Speed”等。
示例输出:
[{'Attack': 30.0,
'Defense': 50.0,
'HP': 40.0,
'Name': 'Voltorb',
'SpecialAttack': 55.0,
'SpecialDefense': 55.0,
'Speed': 100.0,
'Total': 330.0,
'Type': 'Electric'},
{'Attack': 30.0,
'Defense': 33.0,
'HP': 32.0,
'Name': 'Pikachu',
'SpecialAttack': 55.0,
'SpecialDefense': 55.0,
'Speed': 100.0,
'Total': 330.0,
'Type': 'Electric'},
... etc
]
我会把它坚持到
的功能中def filtered_pokedex(pokedex_data, filter=filter_options):
....etc
但可以自己解决这个问题
如果它需要更好的解释或编辑只是让我知道欢呼...首先在堆栈交换的问题,所以希望我提供了足够的信息
干杯
答案 0 :(得分:2)
在此方案中使用all
。检查值是数字类型还是字符串类型,并相应地改变您的条件。
def foo(vp, k, v):
return vp[k] > v if isinstance(v, (int, float)) else vp[k] == v
for kp, vp in pokedex.iteritems():
if all(foo(vp, k, v) for k, v in filter_options.iteritems()):
print vp
我已经定义了一个函数foo
来处理检查,因为它整理了代码。
答案 1 :(得分:0)
这是一个熊猫解决方案:
import pandas as pd
df = pd.DataFrame(pokedex).T
df # change last entry to Type = "Electric" for demo output.
Attack Defense HP Name ... Type
1 49 49 45 Bulbasaur ... GrassPoison
2 62 63 60 Ivysaur ... GrassPoison
3 82 83 80 Venusaur ... Electric
现在基于filter_options
构建一个布尔掩码:
mask = [True] * len(df)
for key in filter_options:
if isinstance(filter_options[key], int):
mask = mask & (df[key] >= filter_options[key]).values
elif isinstance(filter_options[key], str):
mask = mask & (df[key] == filter_options[key]).values
else:
continue
df.loc[mask]
Attack Defense HP Name ... Type
3 82 83 80 Venusaur ... Electric
答案 2 :(得分:0)
用Python回答你的问题:递归过滤"单个过滤"对于每个选项,直到产生结果。为了使单个过滤器更适合,filter_options被重新组织以包含更多信息。
但是在允许不同的操作类型时会变得复杂。这个问题没有明确地询问这个问题,但确实要求它超越第一个例子。在一组过滤器中允许多种操作类型的最简单的解决方案是"开关"比如包含每个可能操作的函数的构造,但是更好的"解决方案是从标准运算符库传递运算符本身。
# pokedex = ...
filter_options = [
{
'attribute': 'Attack',
'operator': '>=',
'value': 25,
},
{
'attribute': 'Defense',
'operator': '>=',
'value': 30,
},
{
'attribute': 'Type',
'operator': '==',
'value': 'Electric',
},
]
# Better to use: https://docs.python.org/2/library/operator.html
operators = {
'<': lambda a, b: a < b,
'>': lambda a, b: a > b,
'==': lambda a, b: a == b,
'<=': lambda a, b: a <= b,
'>=': lambda a, b: a >= b,
}
def filter_single(attribute, operator, value, pokedex=pokedex):
result = {}
for number, pokemon in pokedex.iteritems():
if operators[operator](pokemon[attribute], value):
result[number] = pokemon
return result
def filter(filter_options, pokedex=pokedex):
result = filter_single(
filter_options[0]['attribute'],
filter_options[0]['operator'],
filter_options[0]['value'],
pokedex,
)
for option in filter_options[1:]:
result = filter_single(
option['attribute'],
option['operator'],
option['value'],
result,
)
return result
print filter(filter_options)
此代码已使用Python 3进行测试,但应与2.7一起使用。将print
替换为print()
,将.iteritems()
替换为.items()
,以转换为Python3。
使用结构化查询语言(SQL)来思考这种类型的查询是微不足道的。将数据结构连接到思维模式是SQL的目的之一。
示例:
SELECT * FROM pokedex
WHERE attack >= 25
AND defense >= 30
AND type == 'Electric';
P.S。我认为这个问题的描述缺少了&#34;扑克&#34;变量似乎是所有口袋妖怪可用的属性,但如果假定过滤器选项始终是有效的属性名称,则不需要。使用FilterOption类是强制执行有效过滤器的一种方法。