我想使用另一个数组finalObject.members
中的值来填充数组allParticipants
。第二个数组(allParticipants
)如下:
allParticipants = [
{
uid:"mem1_100_00",
member: "mem1",
tontine: "100"
total: 785
},
{
uid:"mem1_100_01",
member: "mem1",
tontine: "100"
total: 800
},
{
uid:"mem1_200_00",
member: "mem1",
tontine: "200"
total: 1000
},
{
uid:"mem2_100_00",
member: "mem2",
tontine: "100"
total: 200
},
{
uid:"mem2_200_00",
member: "mem2",
tontine: "200"
total: 7850
},
{
uid:"mem2_200_01",
member: "mem2",
tontine: "200"
total: 5000
},
{
uid:"mem2_200_02",
member: "mem2",
tontine: "200"
total: 1600
},
{
uid:"mem3_100_00",
member: "mem3",
tontine: "100"
total: 150
},
{
uid:"mem3_100_01",
member: "mem3",
tontine: "100"
total: 0
},
{
uid:"mem3_200_00",
member: "mem3",
tontine: "200"
total: 2500
}
]
插入后,第一个数组(finalObject.members
)应该看起来像这样:
finalObject.members = [
{
uid: "mem1",
tontines: {
100:[
{
uid: "mem1_100_00",
total:785
},
{
uid: "mem1_100_01",
total:800
},
],
200:[
{
uid: "mem1_200_00",
total:1000
}
]
}
},
{
uid: "mem2",
tontines: {
100: [
{
uid: "mem2_100_00",
total: 200
}
],
200:[
{
uid: "mem2_200_00",
total: 7850
},
{
uid: "mem2_200_01",
total: 5000
},
{
uid: "mem2_200_02",
total: 1600
}
]
}
},
{
uid: "mem3",
tontines: {
100: [
{
uid: "mem3_100_00",
total: 150
},
{
uid: "mem3_100_01",
total: 0
}
],
200:[
{
uid: "mem3_200_00",
total: 2500
}
]
}
}
]
所以我写了这段代码:
const sizMem = finalObject.members.length;
const sizPartp = allParticipants.length;
for(let idx1=0; idx1<sizPartp; idx1++){
let partP = allParticipants[idx1]
for(let idx2=0; idx2<sizMem; idx2++){
let memP = finalObject.members[idx2];
if(partP.member.localeCompare(memP.uid) == 0){
finalObject.members[idx2].tontines[partP.tontine].push({
uid: partP.uid,
total: partP.total,
})
break
}
}
}
但这就是我得到的:
finalObject.members = [
{
uid: "mem1",
tontines: {
100:[
{
uid: "mem1_100_00",
total:785
},
{
uid: "mem1_100_01",
total:800
},
{
uid: "mem2_100_00",
total: 200
},
{
uid: "mem3_100_00",
total: 150
},
{
uid: "mem3_100_01",
total: 0
}
],
200:[
{
uid: "mem1_200_00",
total:1000
},
{
uid: "mem2_200_00",
total: 7850
},
{
uid: "mem2_200_01",
total: 5000
},
{
uid: "mem2_200_02",
total: 1600
},
{
uid: "mem3_200_00",
total: 2500
}
]
}
},
{
uid: "mem2",
tontines: {
100:[
{
uid: "mem1_100_00",
total:785
},
{
uid: "mem1_100_01",
total:800
},
{
uid: "mem2_100_00",
total: 200
},
{
uid: "mem3_100_00",
total: 150
},
{
uid: "mem3_100_01",
total: 0
}
],
200:[
{
uid: "mem1_200_00",
total:1000
},
{
uid: "mem2_200_00",
total: 7850
},
{
uid: "mem2_200_01",
total: 5000
},
{
uid: "mem2_200_02",
total: 1600
},
{
uid: "mem3_200_00",
total: 2500
}
]
}
},
{
uid: "mem3",
tontines: {
100:[
{
uid: "mem1_100_00",
total:785
},
{
uid: "mem1_100_01",
total:800
},
{
uid: "mem2_100_00",
total: 200
},
{
uid: "mem3_100_00",
total: 150
},
{
uid: "mem3_100_01",
total: 0
}
],
200:[
{
uid: "mem1_200_00",
total:1000
},
{
uid: "mem2_200_00",
total: 7850
},
{
uid: "mem2_200_01",
total: 5000
},
{
uid: "mem2_200_02",
total: 1600
},
{
uid: "mem3_200_00",
total: 2500
}
]
}
}
]
因此,它将为每个成员添加所有元素,而不是仅将新元素添加到相应成员。我已经检查了if
条件(但是将结果写到控制台中),在那部分上一切正常。仅当member
的{{1}}属性与Participant
的{{1}}属性相同时才执行插入。但是,它到处都增加了新元素!
我哪里出错了?
答案 0 :(得分:0)
我哪里出错了?
您的代码太复杂。尝试通过2个嵌入式循环一次完成所有操作。当不需要索引时,使用索引代替(for ... of)。
更精确的诊断:一次按下即可,您必须在其中添加
首先对成员ID进行索引/分组,然后对tontine-id进行索引应该会有所帮助。
var participations = {}
for (let p of allParticipations) {
let member = p.member
if ( ! (member in participations))
participations[member] = { "member": member, "tontines" : {} }
}
let tontine = p.tontine
if ( ! (tontine in participations[member].tontines)) {
participations[member].tontines[tontine] = []
}
participations[member].tontines[tontine].push( { "uid": p.uid, "total": p.total })
}
产生此:
{
mem1: { member: 'mem1', tontines: { '100': [Array], '200': [Array] } },
mem2: { member: 'mem2', tontines: { '100': [Array], '200': [Array] } },
mem3: { member: 'mem3', tontines: { '100': [Array], '200': [Array] } }
}
索引避免了搜索循环。然后,很容易从参与变量中构建所需的内容。
编辑:可以将这种中间数据结构简化为列表的双索引字典
var participations = {}
for (let p of allParticipations) {
if ( ! (p.member in participations)) participations[p.member] = {}
if ( ! (p.tontine in participations[p.member])) participations[p.member][p.tontine] = []
participations[p.member][p.tontine].push({ "uid": p.uid, "total": p.total })
}
结果:
{
mem1: { '100': [ [Object], [Object] ], '200': [ [Object] ] },
mem2: { '100': [ [Object] ], '200': [ [Object], [Object], [Object] ] },
mem3: { '100': [ [Object], [Object] ], '200': [ [Object] ] }
}
编辑2:有时,通用多级索引功能会以更具功能性的风格提供帮助。喜欢:
var x = indexBy(allParticipations,
[ p => p.member, p => p.tontine ], // keys
p => ({ "uid" : p.uid, // items
"total" : p.total
})
)
源代码:
function indexBy(data, extractors, finalizer) {
let all_but_last = extractors.slice(0, extractors.length-1)
let last = extractors[extractors.length-1]
let result = {}
for (let item of data) {
let node = result
for (let extractor of all_but_last) {
let key = extractor(item)
if ( !(key in node)) node[key] = {} // indexing all the way down
node = node[key]
}
let key = last(item)
if ( !(key in node)) node[key] = [] // last level is an array
node[key].push(finalizer(item))
}
return result
}
答案 1 :(得分:0)
无耻的插头。我的小型无依赖库blinq
非常适合这类转换。
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.11"
const output = blinq(allParticipants)
.groupBy(x => x.member)
.select(g => ({
uid: g.key,
member: Object.fromEntries(
g
.groupBy(x => x.tontine)
.select(gg => [
gg.key,
gg.select(x => ({
uid: x.uid,
total: x.total
})).toArray()
])
.toArray()
)
}))
.toArray();
const {
blinq
} = window.blinq
const allParticipants = [{
uid: "mem1_100_00",
member: "mem1",
tontine: "100",
total: 785
},
{
uid: "mem1_100_01",
member: "mem1",
tontine: "100",
total: 800
},
{
uid: "mem1_200_00",
member: "mem1",
tontine: "200",
total: 1000
},
{
uid: "mem2_100_00",
member: "mem2",
tontine: "100",
total: 200
},
{
uid: "mem2_200_00",
member: "mem2",
tontine: "200",
total: 7850
},
{
uid: "mem2_200_01",
member: "mem2",
tontine: "200",
total: 5000
},
{
uid: "mem2_200_02",
member: "mem2",
tontine: "200",
total: 1600
},
{
uid: "mem3_100_00",
member: "mem3",
tontine: "100",
total: 150
},
{
uid: "mem3_100_01",
member: "mem3",
tontine: "100",
total: 0
},
{
uid: "mem3_200_00",
member: "mem3",
tontine: "200",
total: 2500
}
];
const output = blinq(allParticipants)
.groupBy(x => x.member)
.select(g => ({
uid: g.key,
member: Object.fromEntries(
g
.groupBy(x => x.tontine)
.select(gg => [
gg.key,
gg.select(x => ({
uid: x.uid,
total: x.total
})).toArray()
])
.toArray()
)
}))
.toArray();
console.log(JSON.stringify(output, null, 2));