将循环算法与最后一条记录进行比较?
Generalize algorithm for a loop comparing to last record?
我有一个数据集,可以用这个字典列表的玩具示例表示:
data = [{
"_id" : "001",
"Location" : "NY",
"start_date" : "2022-01-01T00:00:00Z",
"Foo" : "fruits"
},
{
"_id" : "002",
"Location" : "NY",
"start_date" : "2022-01-02T00:00:00Z",
"Foo" : "fruits"
},
{
"_id" : "011",
"Location" : "NY",
"start_date" : "2022-02-01T00:00:00Z",
"Bar" : "vegetables"
},
{
"_id" : "012",
"Location" : "NY",
"Start_Date" : "2022-02-02T00:00:00Z",
"Bar" : "vegetables"
},
{
"_id" : "101",
"Location" : "NY",
"Start_Date" : "2022-03-01T00:00:00Z",
"Baz" : "pizza"
},
{
"_id" : "102",
"Location" : "NY",
"Start_Date" : "2022-03-2T00:00:00Z",
"Baz" : "pizza"
},
]
这是 Python 中的一个算法,它收集每个 'collection' 中的每个键,只要有键更改,算法就会将这些键添加到输出中。
data_keys = []
for i, lst in enumerate(data):
all_keys = []
for k, v in lst.items():
all_keys.append(k)
if k.lower() == 'start_date':
start_date = v
this_coll = {'start_date': start_date, 'all_keys': all_keys}
if i == 0:
data_keys.append(this_coll)
else:
last_coll = data_keys[-1]
if this_coll['all_keys'] == last_coll['all_keys']:
continue
else:
data_keys.append(this_coll)
此处给出的正确输出记录了字段名称的每次更改:Foo
、Bar
、Baz
以及字段start_date
中的大小写更改为Start_Date
:
[{'start_date': '2022-01-01T00:00:00Z',
'all_keys': ['_id', 'Location', 'start_date', 'Foo']},
{'start_date': '2022-02-01T00:00:00Z',
'all_keys': ['_id', 'Location', 'start_date', 'Bar']},
{'start_date': '2022-02-02T00:00:00Z',
'all_keys': ['_id', 'Location', 'Start_Date', 'Bar']},
{'start_date': '2022-03-01T00:00:00Z',
'all_keys': ['_id', 'Location', 'Start_Date', 'Baz']}]
是否有涵盖此模式的通用算法将当前项与堆栈中的前一项进行比较?
我需要概括这个算法并找到一个解决方案来对集合中的 MongoDB 文档做完全相同的事情。为了让我发现 Mongo 是否有一个我可以使用的聚合管道运算符,我必须首先了解这个基本算法是否有其他常见形式,以便我知道要寻找什么。
或者非常了解 MongoDB 聚合管道的人可以建议可以产生所需结果的运算符?
itertools.groupby
在键值改变时迭代子迭代器。它会为您跟踪更改的密钥。在您的情况下,这是字典的键。您可以创建一个列表理解,从每个子迭代器中获取第一个值。
import itertools
data = ... your data ...
data_keys = [next(val)
for _, val in itertools.groupby(data, lambda record: record.keys())]
for row in data_keys:
print(row)
结果
{'_id': '001', 'Location': 'NY', 'start_date': '2022-01-01T00:00:00Z', 'Foo': 'fruits'}
{'_id': '011', 'Location': 'NY', 'start_date': '2022-02-01T00:00:00Z', 'Bar': 'vegetables'}
{'_id': '012', 'Location': 'NY', 'Start_Date': '2022-02-02T00:00:00Z', 'Bar': 'vegetables'}
{'_id': '101', 'Location': 'NY', 'Start_Date': '2022-03-01T00:00:00Z', 'Baz': 'pizza'}
编辑:如果你想为此使用查询,一个选项是这样的:
$objectToArray
允许将键格式化为值,$ifNull
允许检查start_date
的几个选项。
$unwind
允许我们对键进行排序。
$group
允许我们撤消 $unwind
,但现在使用排序键
$reduce
从所有键创建一个字符串,这样我们就有东西可以比较了。
- 再次分组,但现在使用我们的字符串,因此我们将只有更改的文档。
db.collection.aggregate([
{
$project: {
data: {$objectToArray: "$$ROOT"},
start_date: {$ifNull: ["$start_date", "$Start_Date"]}
}
},
{$unwind: "$data"},
{$project: {start_date: 1, key: "$data.k", _id: 0}},
{$sort: {start_date: 1, key: 1}},
{$group: {_id: "$start_date", all_keys: {$push: "$key"}}},
{
$project: {
all_keys: 1,
all_keys_string: {
$reduce: {
input: "$all_keys",
initialValue: "",
in: {$concat: ["$$value", "$$this"]}
}
}
}
},
{
$group: {
_id: "$all_keys_string",
all_keys: {$first: "$all_keys"},
start_date: {$first: "$_id"}
}
},
{$unset: "_id"}
])
我有一个数据集,可以用这个字典列表的玩具示例表示:
data = [{
"_id" : "001",
"Location" : "NY",
"start_date" : "2022-01-01T00:00:00Z",
"Foo" : "fruits"
},
{
"_id" : "002",
"Location" : "NY",
"start_date" : "2022-01-02T00:00:00Z",
"Foo" : "fruits"
},
{
"_id" : "011",
"Location" : "NY",
"start_date" : "2022-02-01T00:00:00Z",
"Bar" : "vegetables"
},
{
"_id" : "012",
"Location" : "NY",
"Start_Date" : "2022-02-02T00:00:00Z",
"Bar" : "vegetables"
},
{
"_id" : "101",
"Location" : "NY",
"Start_Date" : "2022-03-01T00:00:00Z",
"Baz" : "pizza"
},
{
"_id" : "102",
"Location" : "NY",
"Start_Date" : "2022-03-2T00:00:00Z",
"Baz" : "pizza"
},
]
这是 Python 中的一个算法,它收集每个 'collection' 中的每个键,只要有键更改,算法就会将这些键添加到输出中。
data_keys = []
for i, lst in enumerate(data):
all_keys = []
for k, v in lst.items():
all_keys.append(k)
if k.lower() == 'start_date':
start_date = v
this_coll = {'start_date': start_date, 'all_keys': all_keys}
if i == 0:
data_keys.append(this_coll)
else:
last_coll = data_keys[-1]
if this_coll['all_keys'] == last_coll['all_keys']:
continue
else:
data_keys.append(this_coll)
此处给出的正确输出记录了字段名称的每次更改:Foo
、Bar
、Baz
以及字段start_date
中的大小写更改为Start_Date
:
[{'start_date': '2022-01-01T00:00:00Z',
'all_keys': ['_id', 'Location', 'start_date', 'Foo']},
{'start_date': '2022-02-01T00:00:00Z',
'all_keys': ['_id', 'Location', 'start_date', 'Bar']},
{'start_date': '2022-02-02T00:00:00Z',
'all_keys': ['_id', 'Location', 'Start_Date', 'Bar']},
{'start_date': '2022-03-01T00:00:00Z',
'all_keys': ['_id', 'Location', 'Start_Date', 'Baz']}]
是否有涵盖此模式的通用算法将当前项与堆栈中的前一项进行比较?
我需要概括这个算法并找到一个解决方案来对集合中的 MongoDB 文档做完全相同的事情。为了让我发现 Mongo 是否有一个我可以使用的聚合管道运算符,我必须首先了解这个基本算法是否有其他常见形式,以便我知道要寻找什么。
或者非常了解 MongoDB 聚合管道的人可以建议可以产生所需结果的运算符?
itertools.groupby
在键值改变时迭代子迭代器。它会为您跟踪更改的密钥。在您的情况下,这是字典的键。您可以创建一个列表理解,从每个子迭代器中获取第一个值。
import itertools
data = ... your data ...
data_keys = [next(val)
for _, val in itertools.groupby(data, lambda record: record.keys())]
for row in data_keys:
print(row)
结果
{'_id': '001', 'Location': 'NY', 'start_date': '2022-01-01T00:00:00Z', 'Foo': 'fruits'}
{'_id': '011', 'Location': 'NY', 'start_date': '2022-02-01T00:00:00Z', 'Bar': 'vegetables'}
{'_id': '012', 'Location': 'NY', 'Start_Date': '2022-02-02T00:00:00Z', 'Bar': 'vegetables'}
{'_id': '101', 'Location': 'NY', 'Start_Date': '2022-03-01T00:00:00Z', 'Baz': 'pizza'}
编辑:如果你想为此使用查询,一个选项是这样的:
$objectToArray
允许将键格式化为值,$ifNull
允许检查start_date
的几个选项。$unwind
允许我们对键进行排序。$group
允许我们撤消$unwind
,但现在使用排序键$reduce
从所有键创建一个字符串,这样我们就有东西可以比较了。- 再次分组,但现在使用我们的字符串,因此我们将只有更改的文档。
db.collection.aggregate([
{
$project: {
data: {$objectToArray: "$$ROOT"},
start_date: {$ifNull: ["$start_date", "$Start_Date"]}
}
},
{$unwind: "$data"},
{$project: {start_date: 1, key: "$data.k", _id: 0}},
{$sort: {start_date: 1, key: 1}},
{$group: {_id: "$start_date", all_keys: {$push: "$key"}}},
{
$project: {
all_keys: 1,
all_keys_string: {
$reduce: {
input: "$all_keys",
initialValue: "",
in: {$concat: ["$$value", "$$this"]}
}
}
}
},
{
$group: {
_id: "$all_keys_string",
all_keys: {$first: "$all_keys"},
start_date: {$first: "$_id"}
}
},
{$unset: "_id"}
])