簡體   English   中英

用另一個包含多個項目的字典過濾一個字典

[英]Filtering a dictionary with another dictionary containing multiple items

我有一本字典,我想用另一本字典(其中有“過濾器選項”顯示在這篇文章的一半下方)進行過濾。 我可以為單個項目而不是整個字典找出一些東西...我已經看了一會兒了,但其他答案僅是一個條目的過濾器(字典理解很好地解決了)

這是我到目前為止對單項字典過濾器所做的,即

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且類型==“ Electric”的記錄。還要預料到也可以傳遞其他參數,例如“ 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

但可以自己解決

如果它需要更好地解釋或編輯,請讓我知道歡呼...關於堆棧交換的第一個問題,希望我提供了足夠的信息

干杯

在此情況下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來處理檢查,因為它整理了代碼。

這是熊貓的解決方案:

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     

在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';

PS:我認為問題的描述缺少“ pokers”變量似乎是所有口袋妖怪可用的屬性,但是如果假定過濾器選項始終是有效的屬性名稱,則不需要這樣做。 使用FilterOption類是強制使用有效過濾器的一種方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM