所以这是一个问题,我什至不知道从哪里开始,所以即使指向正确方向的指针也很好。
所以我有看起来像这样的数据:
data = {
"agg": {
"agg1": [
{
"keyWeWant": "*-20.0",
"asdf": 0,
"asdf": 20,
"asdf": 14,
"some_nested_agg": [
{
"keyWeWant2": 20,
"to": 25,
"doc_count": 4,
"some_nested_agg2": {
"count": 7,
"min": 2,
"max": 5,
"keyWeWant3": 2.857142857142857,
"sum": 20
}
},
{
"keyWeWant2": 25,
"to": 30,
"doc_count": 10,
"some_nested_agg2": {
"count": 16,
"min": 2,
"max": 10,
"keyWeWant3": 6.375,
"sum": 102
}
}
]
},
{
...
},
{
...
},
...
]
}
}
现在从示例中,在“agg”中有N个“agg1”结果,在每个“agg1”结果中都有一个“keyWeWant”。每个“agg1”结果还具有“some_nested_agg”结果列表,每个结果都包含一个“keyWeWant2”。每个“keyWeWant2”值都与层次结构中某个位置的单个“keyWeWant”值相关联。同样,每个“keyWeWant2”也包含“some_nested_agg2”的一组结果(这次不是列表,而是 map )。每个结果集都包含一个“keyWeWant3”。
现在,我想在保持“keyWeWant”,“keyWeWant2”和“keyWeWant3”(本质上是去规范化)之间的关联的同时,使结构扁平化,以获得如下所示的内容:
我想要的功能看起来像什么:
[
{
"keyWeWant" : "*-20",
"keyWeWant2" : 20,
"keyWeWant3" : 2.857142857142857
},
{
"keyWeWant" : "*-20",
"keyWeWant2" : 25,
"keyWeWant3" : 6.375
},
{
...
},
{
...
}
]
这是一个示例,其中只有深度3,但是可能存在任意深度,其中一些嵌套值是列表,而有些是数组/列表。
我想做的是编写一个函数,以接收想要的密钥以及在哪里可以找到它们,然后去获取密钥并进行非规范化。
看起来像这样:
function_name(data_map, {
"keyWeWant" : ['agg', 'agg1'],
"keyWeWant2" : ['agg', 'agg1', 'some_nested_agg'],
"keyWeWant" : ['agg', 'agg1', 'some_nested_agg', 'some_nested_agg2']
})
有任何想法吗?我熟悉Java,Clojure,Java脚本和Python,并且正在寻找一种相对简单的解决方法。
最佳答案
这是您可以使用的JavaScript(ES6)函数:
function flatten(data, keys) {
var key = keys[0];
if (key in data)
keys = keys.slice(1);
var res = keys.length && Object.keys(data)
.map( key => data[key] )
.filter( val => Object(val) === val )
.reduce( (res, val) => res.concat(flatten(val, keys)), []);
return !(key in data) ? res
: (res || [{}]).map ( obj => Object.assign(obj, { [key]: data[key] }) );
}
// Sample data
var data = {
"agg": {
"agg1": [
{
"keyWeWant": "*-20.0",
"asdf": 0,
"asdf": 20,
"asdf": 14,
"some_nested_agg": [
{
"keyWeWant2": 20,
"to": 25,
"doc_count": 4,
"some_nested_agg2": {
"count": 7,
"min": 2,
"max": 5,
"keyWeWant3": 2.857142857142857,
"sum": 20
}
},
{
"keyWeWant2": 25,
"to": 30,
"doc_count": 10,
"some_nested_agg2": {
"count": 16,
"min": 2,
"max": 10,
"keyWeWant3": 6.375,
"sum": 102
}
}
]
},
]
}
};
// Flatten it by array of keys
var res = flatten(data, ['keyWeWant', 'keyWeWant2', 'keyWeWant3']);
// Output result
console.log(res);
替代使用路径
如注释中所述,上面的代码不使用路径信息。它只是看起来在所有数组中。如果要查找的键也出现在应忽略的路径中,则可能是一个问题。
以下替代方法将使用路径信息,该信息应作为子数组的数组传递,其中每个子数组首先列出路径键,最后一个元素为要保留的值键:
function flatten(data, [path, ...paths]) {
return path && (
Array.isArray(data)
? data.reduce( (res, item) => res.concat(flatten(item, arguments[1])), [] )
: path[0] in data && (
path.length > 1
? flatten(data[path[0]], [path.slice(1), ...paths])
: (flatten(data, paths) || [{}]).map (
item => Object.assign(item, { [path[0]]: data[path[0]] })
)
)
);
}
// Sample data
var data = {
"agg": {
"agg1": [
{
"keyWeWant": "*-20.0",
"asdf": 0,
"asdf": 20,
"asdf": 14,
"some_nested_agg": [
{
"keyWeWant2": 20,
"to": 25,
"doc_count": 4,
"some_nested_agg2": {
"count": 7,
"min": 2,
"max": 5,
"keyWeWant3": 2.857142857142857,
"sum": 20
}
},
{
"keyWeWant2": 25,
"to": 30,
"doc_count": 10,
"some_nested_agg2": {
"count": 16,
"min": 2,
"max": 10,
"keyWeWant3": 6.375,
"sum": 102
}
}
]
},
]
}
};
// Flatten it by array of keys
var res = flatten(data, [
['agg', 'agg1', 'keyWeWant'],
['some_nested_agg', 'keyWeWant2'],
['some_nested_agg2', 'keyWeWant3']]);
// Output result
console.log(res);