簡體   English   中英

python根據條件將字典列表分為兩個列表

[英]python split list of dictionaries into two lists based on conditional

我試圖根據條件是字典中值的類型將字典列表分為兩個列表。 無論如何,在一次通過列表理解中可以做到這一點嗎?

目前,我正在這樣做:

nonvals = [{k: v for k, v in act.items() if type(v) != int} for act in actual]
vals = [{k: v for k, v in act.items() if type(v) == int} for act in actual]

無論如何,我是否可以基於一個列表理解中的條件返回兩個列表? 如果不是,還有什么更Python的方式來拆分此詞典列表?

我嘗試將以下內容作為最終解決方案,但我覺得可以避免很多代碼重復和無關的循環- actualexpected參考是字典列表。 我想以最少的行數得出最終解決方案。

我想檢查非int鍵,期望值對是否在非int鍵,實際值對中。 實際上,我只想檢查所有int鍵,值對是否在[-11,11]范圍內。


expected = [{'time': '12:34:22', 'place': 'LA', 'person': 'Mike', 'val1': 2, 'val2': 3, 'val3': 4},
            {'time': '11:45:15', 'place': 'SF', 'person': 'Emily', 'val1': 2, 'val2': 3, 'val3': 4}]

actual = [{'time': '12:34:22', 'place': 'LA', 'person': 'Mike', 'val1': 2, 'val2': 3, 'val3': 4},
          {'time': '11:45:15', 'place': 'SF', 'person': 'Emily', 'val1': 2, 'val2': 3, 'val3': 4},
          {'time': '21:19:57', 'place': 'LA', 'person': 'Leo', 'val1': 2, 'val2': 3, 'val3': 4},
          {'time': '15:43:11', 'place': 'LA', 'person': 'Marge', 'val1': 2, 'val2': 3, 'val3': 4}]

def check(expected, actual):

    nonvals = [{k: v for k, v in act.items() if type(v) != int} for act in actual]
    vals = [{k: v for k, v in act.items() if type(v) == int} for act in actual]


    for act in actual:
       for k, v in act.items():
           if v in vals and v not in range(-11, 11):
                 return False

    for exp in expected:
       if {k: v for k, v in exp.items() if type(v) != int} not in nonvals:
           return False

    return True

沒有通用的pythonic解決方案可以根據某種條件拆分列表,更不用說根據某種條件(如與特定類型匹配的值的類型)拆分字典的工作了。

做您的工作很容易閱讀,而且不是一個不好的解決方案,但是如果您經常遇到此問題,則可以編寫一個函數,然后將其應用於列表中的字典:

def pdict(d, condition):
    """
    Partition a dictionary based on some condition function
    :param d: a dict
    :param condition: a function with parameters k, v returning a bool for k: v in d
    :return: two dictionaries, with the contents of d, split according to condition
    """
    return {
        k: v for k, v in d.items() if condition(k, v)
    }, {
        k: v for k, v in d.items() if not condition(k, v)
    }  


original = [{'a': 1, 'b': 'two', 'c': 3}, {'a': 'one', 'b': 2}, {'a': 1, 'b': 2}]
int_result, nonint_result = [
    list(t) for t in zip(*[
        pdict(d, lambda k, v: isinstance(v, int)) for d in original
    ])   
]

print(int_result)
print(nonint_result)

這很干凈,可以讓您在類似情況下簡單地重用partition_dict

該示例產生的輸出:

[{'a': 1, 'c': 3}, {'b': 2}, {'a': 1, 'b': 2}]
[{'b': 'two'}, {'a': 'one'}, {}]

(重新)使用pdict()更簡單示例:

d = {1: 42, 2: 33, 3: 5, 4: 10}
odd, even = pdict(d, lambda k, v: v % 2 == 1)
print(odd, even)

輸出:

{2: 33, 3: 5} {1: 42, 4: 10}

pdict()重寫僅循環一次(如@blues所建議),但有點冗長:

def pdict(d, condition):
    """
    Partition a dictionary based on some condition function
    :param d: a dict
    :param condition: a function with parameters k, v returning a bool for k: v in d
    :return: two dictionaries, with the contents of d, split according to condition
    """
    meets_condition = {}
    does_not_meet_condition = {}
    for k, v in d.items():
        if condition(k, v):
            meets_condition[k] = v
        else:
            does_not_meet_condition[k] = v
    return meets_condition, does_not_meet_condition

這樣的缺點可能是,對於每個添加到字典的元素,查找中可能會有一些開銷,原始示例代碼可以避免字典理解中的開銷。 您可以運行性能測試來確定最佳選擇,但是后一種解決方案的確避免了遍歷整個原始字典兩次。 我想我希望第一個解決方案能夠解決所有瘋狂的事情。

暫無
暫無

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

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