根据重复的字典属性将一维列表减少为锯齿状的二维列表

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 的解决方案。

基本上,我们使用不同的 latitudelongitude 作为键来构建一个对象以获得唯一键,如果它重复我们创建一个数组(如果之前没有创建)然后推送项目。

我认为这对于您的目的来说非常可读且高效。

注意:根据用户要求,已更正为数组中的所有内容。

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)