简体   繁体   English

基于另一个数组的es6过滤器数组

[英]es6 filter array based on another array with out mutating

filtering arrays has been asked here a lot but none of the questions and answers i found took in consideration the 2 conditions i need: 过滤数组在这里已经被问了很多,但是我发现的问题和答案都没有考虑到我需要的两个条件:
1. not mutating the objects. 1.不改变对象。
2. using es6 (ecmascript2015) and above. 2.使用es6(ecmascript2015)及更高版本。
3. get a new array that holds the overriten objects and values. 3.获得一个新数组,其中包含被覆盖的对象和值。

i actually have an answer to one part of my question and that is how to filter but it feels like a hack rather than a real solution, the second part is how to get the full original array with the changes from the second array but without mutating the objects. 我实际上对我的问题的一部分有一个答案,那就是如何过滤,但是感觉就像是黑客,而不是真正的解决方案,第二部分是如何从第二个数组中获得更改而获得完整的原始数组,而又不会发生变化对象。

This is my code, as you can see i'm assigning the {dirty:true} explicitly rather than pass the object from the array it self: 这是我的代码,如您所见,我正在显式地分配{dirty:true}而不是通过其自身的数组传递对象:

    const docPositions = [
    {
      active : false,
      dirty : false,
      key : "somekey2"
    },
    {
      active : false,
      dirty : false,
      key : "somekey1"
    },
    {
      active : false,
      dirty : false,
      key : "somekey4"
    },
    {
      active : false,
      dirty : false,
      key : "somekey3"
    }
  ]
const dirtyPositions = [
  {
      active : false,
      dirty : true,
      key : "somekey1"
  },
    {
      active : false,
      dirty : true,
      key : "somekey3"
  } 
]

let result = docPositions.filter(x=> dirtyPositions.some(y=>y.key == x.key))
                         .map(o=> Object.assign({},o,{dirty:true}));

console.log(result);

result: 结果:

Array [
  Object {
    "active": false,
    "dirty": true,
    "key": "somekey1"
  },
  Object {
    "active": false,
    "dirty": true,
    "key": "somekey3"
  }
]

desired result: 预期结果:

 Array   [
    {
      active : false,
      dirty : false,
      key : "somekey2"
    },
    {
      active : false,
      dirty : true,
      key : "somekey1"
    },
    {
      active : false,
      dirty : false,
      key : "somekey4"
    },
    {
      active : false,
      dirty : true,
      key : "somekey3"
    }
  ]

You could do it by using find on the dirty positions, which either returns undefined or the dirty object. 您可以通过在脏位置使用find来执行此操作,该位置返回undefined或脏对象。 If you put that as third argument to Object.assign together with the matching docPosition in second position, you will get the desired result: 如果将它作为Object.assign第三个参数以及匹配的docPosition放在第二个位置,则将获得所需的结果:

const result = docPositions.map(
    x => Object.assign({}, x, dirtyPositions.find(y=>y.key == x.key)));

 const docPositions = [ { active : false, dirty : false, key : "somekey2" }, { active : false, dirty : false, key : "somekey1" }, { active : false, dirty : false, key : "somekey4" }, { active : false, dirty : false, key : "somekey3" } ] const dirtyPositions = [ { active : false, dirty : true, key : "somekey1" }, { active : false, dirty : true, key : "somekey3" } ] const result = docPositions.map( x => Object.assign({}, x, dirtyPositions.find(y=>y.key == x.key))); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

For large arrays... 对于大型阵列...

The above has a time complexity of O(n²) , so when both arrays are large, then performing .find() on each .map() iteration may become too costly. 上面的时间复杂度为O(n²) ,因此,当两个数组都很大时,对每个.map()迭代执行.find()可能会变得过于昂贵。 In that case it is better to first turn the dirtyPositions array into a Map . 在这种情况下,最好先将dirtyPositions数组转换为Map To keep with the functional programming style, you could pass that Map as the context to .map() so it is available as this . 为了与函数式编程风格保持一致,您可以将该Map作为上下文传递给.map()以便可以使用this For that you need to use the standard function notation though: 为此,您需要使用标准function符号:

const result = docPositions.map(function (x) { 
    return Object.assign({}, x, this.get(x.key));
}, new Map(dirtyPositions.map(y=>[y.key, y])));

This will run in O(n) , as the get() operation is in most implementations near-constant in time. 这将在O(n)中运行,因为在大多数实现中get()操作在时间上几乎是恒定的。

 const docPositions = [ { active : false, dirty : false, key : "somekey2" }, { active : false, dirty : false, key : "somekey1" }, { active : false, dirty : false, key : "somekey4" }, { active : false, dirty : false, key : "somekey3" } ] const dirtyPositions = [ { active : false, dirty : true, key : "somekey1" }, { active : false, dirty : true, key : "somekey3" } ] const result = docPositions.map(function (x) { return Object.assign({}, x, this.get(x.key)); }, new Map(dirtyPositions.map(y=>[y.key, y]))); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Note that the Map constructor can take an array of key/value pairs (also arrays). 请注意, Map构造函数可以采用键/值对的数组(也可以是数组)。 This new Map is passed as the optional thisArg to .map() so that it can be referenced to with this inside the callback. 将此新Map作为可选的thisArg传递给.map()以便可以在回调内部this进行引用。

This should match as an ES6 answer 这应该作为ES6答案匹配

 const docPositions = [ { active : false, dirty : false, key : "somekey2" }, { active : false, dirty : false, key : "somekey1" }, { active : false, dirty : false, key : "somekey4" }, { active : false, dirty : false, key : "somekey3" } ] const dirtyPositions = [ { active : false, dirty : true, key : "somekey1" }, { active : false, dirty : true, key : "somekey3" } ]; const dirtyKeys = dirtyPositions.map(x => x.key); var results = docPositions.map(x => { let index = dirtyKeys.indexOf(x.key); if (index === -1) return x; return dirtyPositions[index]; }) console.log(results); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM