gpt4 book ai didi

javascript - 将带有普通对象数组的普通对象展开为平面普通对象

转载 作者:行者123 更新时间:2023-11-27 22:48:12 25 4
gpt4 key购买 nike

更新:我以错误的方式描述了问题,并完全重写了描述,以及有效但丑陋且有限的代码。

<小时/>

假设有一个物体

const input = {
a: 1,
b: '2',
c: {
d: true,
e: '4'
},
f: [{
g: 5,
h: {
i: '6'
}
}, {
g: 7,
h: {
i: '8'
}
}]
}

我正在寻找的是嵌套数组的所有可能排列的集合,其中对象的键被展平并用“.”连接,例如

[{
a: 1,
b: '2',
'c.d': true,
'c.e': '4',
'f.g': 5,
'f.h.i': '6'
}, {
a: 1,
b: '2',
'c.d': true,
'c.e': '4',
'f.g': 7,
'f.h.i': '8'
}]

请注意,没有任何键具有非原始值,例如,'f.h' 会指向一个对象。

所以,我首先要做的就是收集所有键,并人为地向指向数组项的每个键添加 # 符号,所以 # 是一种意思“该数组中的每个索引”:

function columns(data, prefix = '') {
if (_.isArray(data)) {
return columns(_.first(data), `${prefix}.#`);
} else if (_.isObject(data)) {
return _.filter(_.flatMap(_.keys(data), key => {
return _.concat(
!_.isObject(_.result(data, key)) ? `${prefix}.${key}` : null,
columns(data[key], `${prefix}.${key}`)
);
}));
} else {
return null;
}
}

console.log(columns(input)); // -> [".a", ".b", ".c.d", ".c.e", ".f.#.g", ".f.#.h.i"]

现在,我挥舞着洛达什。前导“.” in 键对于 lodash 来说不是问题,所以我就保持原样。使用 lodash,我将对象压缩为具有奇怪键的一级对象:

function flattenKeys(original, keys) {
return _.mapValues(_.groupBy(_.map(keys, key => ({
key,
value: _.result(original, key)
})), 'key'), e => _.result(e, '0.value'));
}

console.log(flattenKeys(input, columns(input))) // -> {".a":1,".b":"2",".c.d":true,".c.e":"4"}

现在我(以一种非常错误的方式)运行原始对象的每个类似数组的属性,并生成一个对象数组,设置像 .f.#.h.i 这样的键,其值是.f.0.h.i 用于第一个元素等:

function unfold(original, keys, iterables) {
if (!_.isArray(iterables)) {
return unfold(original, keys, _.uniq(_.map(_.filter(keys, key => /#/i.test(key)), key => _.replace(key, /\.\#.*/, ''))));
} else if (_.isEmpty(iterables)) {
return [];
} else {
const first = _.first(iterables);
const rest = _.tail(iterables);
const values = _.result(original, first);
const flatKeys = _.mapKeys(_.filter(keys, key => _.includes(key, first)));
const updated = _.map(values, (v, i) => ({
...flattenKeys(original, keys),
..._.mapValues(flatKeys, k => _.result(original, _.replace(k, /\#/, i)))
}));

return _.concat(updated, unfold(original, keys, rest));
}
}

console.log(unfold(input, columns(input))) // -> [{".a":1,".b":"2",".c.d":true,".c.e":"4",".f.#.g":5,".f.#.h.i":"6"},{".a":1,".b":"2",".c.d":true,".c.e":"4",".f.#.g":7,".f.#.h.i":"8"}]

所以最后,我只需要清理按键,事实上,这在我的情况下是不必要的。

问题是,除了代码的丑陋之外,我怎样才能让它与原始对象中可能的多个类似数组的属性一起工作?

<小时/>

现在,我明白,这个问题更适合 CodeReview StackExchange,所以如果有人将其转移到那里,我可以接受。

最佳答案

根据您更新的结构,以下递归函数可以解决问题:

function unfold(input) {
function flatten(obj) {
var result = {},
f,
key,
keyf;

for(key in obj) {
if(obj[key] instanceof Array) {
obj[key].forEach(function(k) {
f = flatten(k);
for(keyf in f) {
result[key+'.'+keyf] = f[keyf];
}
output.push(JSON.parse(JSON.stringify(result))); //poor man's clone object
});
} else if(obj[key] instanceof Object) {
f = flatten(obj[key]);
for(keyf in f) {
result[key+'.'+keyf] = f[keyf];
}
} else {
result[key] = obj[key];
}
}
return result;
} //flatten

var output = [];
flatten(input);
return output;
} //unfold

片段:

function unfold(input) {
function flatten(obj) {
var result = {},
f,
key,
keyf;

for(key in obj) {
if(obj[key] instanceof Array) {
obj[key].forEach(function(k) {
f = flatten(k);
for(keyf in f) {
result[key+'.'+keyf] = f[keyf];
}
output.push(JSON.parse(JSON.stringify(result))); //poor man's clone object
});
} else if(obj[key] instanceof Object) {
f = flatten(obj[key]);
for(keyf in f) {
result[key+'.'+keyf] = f[keyf];
}
} else {
result[key] = obj[key];
}
}
return result;
} //flatten

var output = [];
flatten(input);
return output;
} //unfold

const input = {
a: 1,
b: '2',
c: {
d: true,
e: '4'
},
f: [{
g: 5,
h: {
i: '6'
}
}, {
g: 7,
h: {
i: '8'
}
}]
};

document.body.innerHTML+= '<pre>' + JSON.stringify(unfold(input), null, 2) + '</pre>';

<小时/>

我将留下我原来的答案,它适用于您的原始结构:

var o = {a: [{b: 1, c: 2}], d: [{e: 4, f: 5}]},
keys = Object.keys(o),
result = [];

keys.forEach(function(i, idx1) {
keys.forEach(function(j, idx2) {
if(idx2 > idx1) { //avoid duplicates
for(var k in o[i][0]) {
for(var l in o[j][0]) {
result.push({
[i + '.' + k]: o[i][0][k],
[j + '.' + l]: o[j][0][l]
});
}
}
}
});
});

console.log(JSON.stringify(result));

关于javascript - 将带有普通对象数组的普通对象展开为平面普通对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38257672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com