根据重复的字典属性将一维列表减少为锯齿状的二维列表
Reduce 1D list into jagged 2D list based on duplicate dictionary properties
我有一个这样的字典列表,可能包含基于一些字典属性(不是所有属性)的重复项:
const data = [{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'x',
latitude: '45.9',
longitude: '50.2'
}, {
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}];
在这里,如果两个词典共享相同的经度和纬度,则它们被认为是重复的。
我们的目标是减少这个 1D 列表,将一种类型的所有重复项分组到一个嵌套列表中。例如,如果我们有三个具有相同坐标的副本,它们应该进入自己的嵌套列表,而另一个坐标的两个副本进入不同的嵌套列表。即使是没有重复的独立坐标也应该进入它自己的嵌套列表。我们希望得到一个列表,其中每个项目都是一个表示唯一坐标的列表。
期望的输出:
[
[
{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}
],
[
{
name: 'x',
latitude: '45.9',
longitude: '50.2'
}
],
[
{
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}
]
];
编辑:更正了所需的输出,以便所有项目都是列表。
我将从将每个数据点放入一个对象开始。我会使用坐标 (lat,lng) 作为指向每个唯一坐标的数组的键。当您遍历数据点时,您可以将每个数据点添加到对象中各自的数组中。
然后遍历您刚创建的那个对象的值。每个值都应该是一个数组。如果该数组的长度为 1,您可以只将该对象添加到您的输出数组,但如果它大于 1,您可以将整个数组添加到您的输出数组。
瞧。
const data = [{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'x',
latitude: '45.9',
longitude: '50.2'
}, {
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}];
let obj = {};
data.forEach(e => {
let key = `${e.latitude},${e.longitude}`;
if(obj[key] == undefined)
obj[key] = [];
obj[key].push(e);
});
let output = [];
Object.values(obj).forEach(e => {
if(e.length == 1)
output.push(e[0]);
else
output.push(e);
});
console.log(output);
虽然有很多选择,但我更喜欢使用 reduce
的解决方案。
基本上,我们使用不同的 latitude
和 longitude
作为键来构建一个对象以获得唯一键,如果它重复我们创建一个数组(如果之前没有创建)然后推送项目。
我认为这对于您的目的来说非常可读且高效。
注意:根据用户要求,已更正为数组中的所有内容。
const data = [{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'x',
latitude: '45.9',
longitude: '50.2'
}, {
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}];
const reducer = (accum, cv, i) => {
// create a key using the lat and lng
const key = `${cv.latitude}-${cv.longitude}`;
// if the key was already there, we need to push it.
if (accum[key]) {
accum[key] = [...accum[key], cv]
} else {
// if not, we just create an array with the entry
accum[key] = [cv];
}
return accum;
};
const objectMapped = data.reduce(reducer, {});
// then we get an object, to get the values we use this function.
const result = Object.values(objectMapped);
console.log(result);
你可以这样做:
const data = [{ name: 'v', latitude: '30.0', longitude: '25.0' },{ name: 'w', latitude: '30.0', longitude: '25.0' },{ name: 'x', latitude: '45.9', longitude: '50.2' },{ name: 'y', latitude: '40.5', longitude: '85.7' },{ name: 'z', latitude: '40.5', longitude: '85.7' },]
const result = Object.values(data.reduce((a, c) => {
const k = `${c.latitude}${c.longitude}`
return (a[k] = [...(a[k] || []), c], a)
}, {}))
console.log(result)
我有一个这样的字典列表,可能包含基于一些字典属性(不是所有属性)的重复项:
const data = [{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'x',
latitude: '45.9',
longitude: '50.2'
}, {
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}];
在这里,如果两个词典共享相同的经度和纬度,则它们被认为是重复的。
我们的目标是减少这个 1D 列表,将一种类型的所有重复项分组到一个嵌套列表中。例如,如果我们有三个具有相同坐标的副本,它们应该进入自己的嵌套列表,而另一个坐标的两个副本进入不同的嵌套列表。即使是没有重复的独立坐标也应该进入它自己的嵌套列表。我们希望得到一个列表,其中每个项目都是一个表示唯一坐标的列表。
期望的输出:
[
[
{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}
],
[
{
name: 'x',
latitude: '45.9',
longitude: '50.2'
}
],
[
{
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}
]
];
编辑:更正了所需的输出,以便所有项目都是列表。
我将从将每个数据点放入一个对象开始。我会使用坐标 (lat,lng) 作为指向每个唯一坐标的数组的键。当您遍历数据点时,您可以将每个数据点添加到对象中各自的数组中。
然后遍历您刚创建的那个对象的值。每个值都应该是一个数组。如果该数组的长度为 1,您可以只将该对象添加到您的输出数组,但如果它大于 1,您可以将整个数组添加到您的输出数组。
瞧。
const data = [{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'x',
latitude: '45.9',
longitude: '50.2'
}, {
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}];
let obj = {};
data.forEach(e => {
let key = `${e.latitude},${e.longitude}`;
if(obj[key] == undefined)
obj[key] = [];
obj[key].push(e);
});
let output = [];
Object.values(obj).forEach(e => {
if(e.length == 1)
output.push(e[0]);
else
output.push(e);
});
console.log(output);
虽然有很多选择,但我更喜欢使用 reduce
的解决方案。
基本上,我们使用不同的 latitude
和 longitude
作为键来构建一个对象以获得唯一键,如果它重复我们创建一个数组(如果之前没有创建)然后推送项目。
我认为这对于您的目的来说非常可读且高效。
注意:根据用户要求,已更正为数组中的所有内容。
const data = [{
name: 'v',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'w',
latitude: '30.0',
longitude: '25.0'
}, {
name: 'x',
latitude: '45.9',
longitude: '50.2'
}, {
name: 'y',
latitude: '40.5',
longitude: '85.7'
}, {
name: 'z',
latitude: '40.5',
longitude: '85.7'
}];
const reducer = (accum, cv, i) => {
// create a key using the lat and lng
const key = `${cv.latitude}-${cv.longitude}`;
// if the key was already there, we need to push it.
if (accum[key]) {
accum[key] = [...accum[key], cv]
} else {
// if not, we just create an array with the entry
accum[key] = [cv];
}
return accum;
};
const objectMapped = data.reduce(reducer, {});
// then we get an object, to get the values we use this function.
const result = Object.values(objectMapped);
console.log(result);
你可以这样做:
const data = [{ name: 'v', latitude: '30.0', longitude: '25.0' },{ name: 'w', latitude: '30.0', longitude: '25.0' },{ name: 'x', latitude: '45.9', longitude: '50.2' },{ name: 'y', latitude: '40.5', longitude: '85.7' },{ name: 'z', latitude: '40.5', longitude: '85.7' },]
const result = Object.values(data.reduce((a, c) => {
const k = `${c.latitude}${c.longitude}`
return (a[k] = [...(a[k] || []), c], a)
}, {}))
console.log(result)