【问题标题】:how to filter array for unique id in typescript/javascript [duplicate]如何在打字稿/javascript中过滤数组以获取唯一ID [重复]
【发布时间】:2019-06-02 22:49:28
【问题描述】:

我有一个对象数组,如何在 typescript/javascript 中过滤数组以获取唯一 ID

列表数组-

[{
    global_id: "269a8bded9bd4ecaa0e501c170a71f5a"
    icon: "/odb/icons/ip/ip_32.svg"
    id: "269a8bded9bd4ecaa0e501c170a71f5a"
}, {
    global_id: "269a8bded9bd4ecaa0e501c170a71f5a"
    icon: "/odb/icons/ip/ip_32.svg"
    id: "269a8bded9bd4ecaa0e501c170a71f5a"
}, {
    global_id: 348
    icon: "/odb/icons/ip/ip_32.svg"
    id: 348
}, {
    global_id: 201
    icon: "/odb/icons/ip/ip_32.svg"
    id: 201
}]

以此类推,

我想以不应该列出重复元素的方式过滤我的对象数组。

list.filter()如果可以的话我想用。

_.uniqBy(list, 'id'); 在 lodash 中可用,但我想使用 typescript/javascrpt .filter 方法。 请指导。

【问题讨论】:

标签: javascript arrays typescript


【解决方案1】:

使用Array#reduceMapspread operator

var data =[{global_id:"269a8bded9bd4ecaa0e501c170a71f5a",icon:"/odb/icons/ip/ip_32.svg",id:"269a8bded9bd4ecaa0e501c170a71f5a"},{global_id:"269a8bded9bd4ecaa0e501c170a71f5a",icon:"/odb/icons/ip/ip_32.svg",id:"269a8bded9bd4ecaa0e501c170a71f5a"},{global_id:348,icon:"/odb/icons/ip/ip_32.svg",id:348},{global_id:201,icon:"/odb/icons/ip/ip_32.svg",id:201}];

const res = [...data.reduce((a,c)=>{
  a.set(c.global_id, c);
  return a;
}, new Map()).values()];

console.log(res);

性能

function getRndInteger(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

const keys = [
  'a', 'b', 'c', 'd', 'e', 'f', 'g',
];

const generatedArray = [];

for (let i = 0; i < 100000; i += 1) {
  generatedArray.push({
    global_id: keys[getRndInteger(0, keys.length - 1)],
    val: i,
  });
}

const start = Date.now();

const unique = [...generatedArray.reduce((a,c)=>{
  a.set(c.global_id, c);
  return a;
}, new Map()).values()];

console.log(unique);

console.log(`It took ${Date.now() - start}ms to unique`);

【讨论】:

  • 它在使用时出错,说类型 iterableiterator 不是数组类型。使用它说的编译器选项。
  • @JavascriptCoder 这可能是因为您需要在 .tsconfig 文件(或 webpack.config.js 或 .babelrc 取决于您的设置)中指定更高的 ECMAScript 版本。可能需要尝试 es2016 或 es2017 或 es2018。
【解决方案2】:

这是一个使用 Array.filter 的解决方案

function uniqueArrayOfObject(array, keyToBeUnique) {
  // Filter by looking at the next objects if the key is present a second time
  return array.filter((x, xi) => !array.slice(xi + 1)
    .some(y => y[keyToBeUnique] === x[keyToBeUnique]));
}

function getRndInteger(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

const keys = [
  'a', 'b', 'c', 'd', 'e', 'f', 'g',
];

const generatedArray = [];

for (let i = 0; i < 100000; i += 1) {
  generatedArray.push({
    uniqueKey: keys[getRndInteger(0, keys.length - 1)],
    val: i,
  });
}

const start = Date.now();

const unique = uniqueArrayOfObject(generatedArray, 'uniqueKey');

console.log(unique);

console.log(`It took ${Date.now() - start}ms to unique`);

其他解决方案(更快)

function uniqueArrayOfObject(array, keyToBeUnique) {
  return Object.values(array.reduce((tmp, x) => {
    // You already get a value
    if (tmp[x[keyToBeUnique]]) return tmp;

    // You never envcountered this key
    tmp[x[keyToBeUnique]] = x;

    return tmp;
  }, {}));
}

function getRndInteger(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

const keys = [
  'a', 'b', 'c', 'd', 'e', 'f', 'g',
];

const generatedArray = [];

for (let i = 0; i < 100000; i += 1) {
  generatedArray.push({
    uniqueKey: keys[getRndInteger(0, keys.length - 1)],
    val: i,
  });
}

const start = Date.now();

const unique = uniqueArrayOfObject(generatedArray, 'uniqueKey');

console.log(unique);

console.log(`It took ${Date.now() - start}ms to unique`);

【讨论】:

  • 如果数组没有排序,我们必须排序并这样做。
  • 如果 global_id 后面的值相同,则无需排序。如果他们不是,是的,你必须这样做。或者您可以使用一个函数来确定要保留哪个
  • 我的数组计数为 10000 列表,这是就性能而言最好的方法。请指导。
  • 我已经用更快的方法编辑了我的帖子
猜你喜欢
  • 2017-04-12
  • 1970-01-01
  • 2017-08-10
  • 1970-01-01
  • 2019-05-04
  • 2020-03-22
  • 1970-01-01
  • 2016-12-17
  • 2016-11-07
相关资源
最近更新 更多