使用filter()过滤python字典到字典值列表

时间:2016-10-20 10:03:34

标签: python dictionary

我有一个由字符串或字典组成的字典

parameters = {
"date": {'date':"2015-12-13"},
"name": "Nick",
"product": "BT Adapter",
"transaction-id": ""
}

我需要获得['2015-12-13', 'BT Adapter', 'Nick']等列表。

如果其中没有字典,print filter(lambda x: x if len(x) > 0 and type(x) is not dict else None, parameters.values())完美无缺,但在字典中,我试图用

提取它的值
print filter(lambda x: x if len(x) > 0 and type(x) is not dict else map(lambda y: x[y], x.keys()), parameters.values())

我得到AttributeError: 'str' object has no attribute 'keys'。 如何提取所有值?

4 个答案:

答案 0 :(得分:4)

您滥用filter功能。 filter的参数是谓词,它是一个返回true / false值的函数,filter返回第二个参数的元素返回true。

例如:

print(list(filter(lambda x: 5, [1,2,3,4,5])))
[1, 2, 3, 4, 5]

由于bool(5) == True过滤器会返回所有元素。

由于您将第parameters.values()作为第二个参数传递,因此只能通过将谓词传递给过滤器来获取预期结果。

你想要做的是:

from itertools import chain

def listify(value):
    if isinstance(value, dict):
        return value.values()
    elif value:
        return [value]
    return ()

print(list(chain.from_iterable(map(listify, parameters.values()))))

首先,您将值转换为序列,然后使用chain.from_iterable将它们连接起来。

listify删除空值,因为在这种情况下它返回一个空序列。样品运行:

In [2]: parameters = {
   ...: "date": {'date':"2015-12-13"},
   ...: "name": "Nick",
   ...: "product": "BT Adapter",
   ...: "transaction-id": ""
   ...: }

In [3]: print(list(chain.from_iterable(map(listify, parameters.values()))))
['2015-12-13', 'Nick', 'BT Adapter']

另外:用嵌套条件写一个复杂的lambda函数没有意义,所以只需使用def并正确编写即可。 lambda只有在非常短的情况下才适用。

答案 1 :(得分:2)

在我看来,您正试图对map进行filter操作,显示出一点误会。过滤器中的函数本质上必须返回TrueFalse以确定是否在第二个参数中保留某个值,因此以这种方式过滤是没有意义的:

filter(lambda x: x if len(x) > 0 and type(x) is not dict else None, parameters.values())

更好:

filter(lambda x: len(x) > 0 and type(x) is not dict, parameters.values())
# better idiom
filter(lambda x: len(x) > 0 and not isinstance(x, dict), parameters.values())

对于您的下一次尝试尤其如此,该尝试尝试{/ 1}} 内部过滤器功能。最好将此视为一个两步过程:

  1. 删除空字符串/列表(map
  2. 的任何内容
  3. 获取字典值
  4. 如果您需要使用lex(x) < 1,请尝试使用此功能。我正在使用Python3,这意味着我必须做很多丑陋的filter投射:

    list

    这会产生:

    list(map(lambda x: list(x.values()) if isinstance(x, dict) else x, filter(lambda x: len(x) > 0, parameters.values())))
    

    这根本不是pythonic:[['2015-12-13'], 'BT Adapter', 'Nick'] filter在列表推导中更像是以下内容:

    map

    如果您在获取字典值后还需要展平列表,请告诉我。

答案 2 :(得分:1)

#!/usr/bin/env python
# -*- coding: utf-8 -*-


def magic(params):
    dicts = [params]
    values = []

    while len(dicts):
        d = dicts.pop()

        for value in d.values():
            if isinstance(value, dict):
                dicts.append(value)
            elif isinstance(value, basestring) and len(value) > 0:
                values.append(value)

    return values


def main():
    parameters = {
        "date": {'date': "2015-12-13"},
        "name": "Nick",
        "product": "BT Adapter",
        "transaction-id": ""
    }

    print(magic(parameters))


if __name__ == '__main__':
    main()

答案 3 :(得分:0)

最后一个属性“transaction-id”失败,因为它的长度为0。

这对你有用:

print filter(lambda x: x if len(x) >= 0 and type(x) is not dict else map(lambda y: x[y], x.keys()), parameters.values())