python - Python3减少函数
问题描述
我在具有重复项的 JS 中使用了以下 dict/JSON:
{
0:{
"id" : 1,
"name": "test"
},
1:{
"id" : 2,
"name": "other name"
},
2:{
"id" : 1,
"name": "does not have to be the same name"
},{
"id" : 3,
"name": "but they could be the same"
},
3:{
"id" : 2,
"name": "other name"
}
}
我想把它减少到:
{
0:{
"id" : 1,
"name": "test"
},
1:{
"id" : 2,
"name": "other name"
},
2:{
"id" : 3,
"name": "but they could be the same"
}
}
标准是 id 必须是唯一的,无论项目的其余部分是否不同。
对于 JS,我使用了以下代码:
const data = [ { "id" : 1, "name": "test" }, { "id" : 2, "name": "other name" }, { "id" : 1, "name": "does not have to be the same name" },{ "id" : 3, "name": "but they could be the same" },{ "id" : 2, "name": "other name" }, ],
unique = Object.values(data.reduce((r, o) => {
r[o.id] = r[o.id] || o;
return r;
},{}));
console.log(unique);
但是,我似乎无法对 python3.9 做同样的事情。我找到了该functools.reduce()
函数并尝试将其与 lambas 一起使用,但 dics 与 JSON 对象不同。
解决方案
请注意,您提供的输入是无效的 JSON。根据你的JS,结构应该是这样的。
foo = [
{
"id" : 1,
"name": "test"
},
{
"id" : 2,
"name": "other name"
},
{
"id" : 1,
"name": "does not have to be the same name"
},
{
"id" : 3,
"name": "but they could be the same"
},
{
"id" : 2,
"name": "other name"
}
]
话虽这么说,如果你想要一个使用 的解决方案reduce
,这样的东西会起作用。
from functools import reduce
foo = [
{
"id" : 1,
"name": "test"
},
{
"id" : 2,
"name": "other name"
},
{
"id" : 1,
"name": "does not have to be the same name"
},
{
"id" : 3,
"name": "but they could be the same"
},
{
"id" : 2,
"name": "other name"
}
]
# in my opinion, the readability suffers here
# sometimes you need to be ok with using more than one line
result = reduce(lambda x, y: x + [y] if not any(i['id'] == y['id'] for i in x) else x, foo, [])
print(result)
一个更易读的例子是使用实际函数而不是lambda
.
from functools import reduce
foo = [
{
"id" : 1,
"name": "test"
},
{
"id" : 2,
"name": "other name"
},
{
"id" : 1,
"name": "does not have to be the same name"
},
{
"id" : 3,
"name": "but they could be the same"
},
{
"id" : 2,
"name": "other name"
}
]
def build_list(result_list, list_element):
if not any(list_element['id'] == i['id'] for i in result_list):
return result_list + [list_element]
return result_list
result = reduce(build_list, foo, [])
print(result)
但这仍然不是我写它的风格。就我个人而言,我会用 a 跟踪重复项set
并完全避免理解 / reduce
。
foo = [
{
"id" : 1,
"name": "test"
},
{
"id" : 2,
"name": "other name"
},
{
"id" : 1,
"name": "does not have to be the same name"
},
{
"id" : 3,
"name": "but they could be the same"
},
{
"id" : 2,
"name": "other name"
}
]
result = []
ids = set()
for dct in foo:
if not dct['id'] in ids:
ids.add(dct['id'])
result.append(dct)
print(result)
推荐阅读
- xslt - 如何在 XSLT 中检查 NaN?
- delphi-10.3-rio - Delphi 10.3.3 FireDAC FDConnection.GetTableNames Interbase
- javascript - 使用对象日期属性对数组进行排序
- php - 如何在两个日期之间创建数组循环
- oracle - 我想将用户定义的数据类型从 ORACLE 转换为有效的 POSTGRE 用户定义数据?
- git - git filter-branch 不会删除我想要的所有文件
- apache2 - Apache2 Xdebug 没有在 PhpStorm 的断点处停止
- javascript - 如何使我的脚本循环并检查所有处于活动状态的按钮?香草js
- sql - What does "@+" and "@*" mean in (oracle) SQL?
- ajax - How to preserve session after ajax call in iframe?