es6过滤器数组基于另一个没有变异的数组

时间:2017-01-21 08:35:29

标签: javascript arrays ecmascript-6 immutability

过滤阵列已在这里被问到很多,但我找到的问题和答案都没有考虑到我需要的两个条件:
1.不改变对象。
2.使用es6(ecmascript2015)及以上。
3.获取一个包含重写对象和值的新数组。

我实际上对我的问题的一部分有一个答案,那就是如何过滤但感觉就像是一个黑客而不是一个真正的解决方案,第二部分是如何从第二个数组获得完整的原始数组但没有改变对象。

这是我的代码,因为你可以看到我明确地分配array.each{|string| puts string.gsub(/12(\s+)?/, '')} ## Output "89" "apples" "546" "3" 而不是自己从数组中传递对象:

{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);

期望的结果:

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

2 个答案:

答案 0 :(得分:5)

您可以在脏位置上使用find来执行此操作,这些位置会返回undefined或脏对象。如果您将其作为第三个参数与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; }

对于大型阵列......

上面的时间复杂度为 O(n²),所以当两个数组都很大时,在每次.find()迭代上执行.map()可能会变得太昂贵。在这种情况下,最好先将dirtyPositions数组转换为Map。为了与函数式编程样式保持一致,您可以将该Map作为上下文传递给.map(),以便它以this的形式提供。为此,您需要使用标准function表示法:

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

这将在 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; }

请注意,Map构造函数可以使用一组键/值对(也是数组)。这个新地图作为可选thisArg传递给.map(),以便在回调中使用this引用它。

答案 1 :(得分:0)

这应该与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);