基于另一个数组的es6过滤器数组没有变异
es6 filter array based on another array with out mutating
过滤数组在这里被问了很多,但是 none 我找到的问题和答案考虑了我需要的 2 个条件:
1. 不改变对象。
2. 使用es6(ecmascript2015)及以上版本
3. 获取一个新数组,其中包含覆盖的对象和值。
我的问题的一部分实际上有一个答案,那就是如何过滤,但感觉像是一个 hack 而不是真正的解决方案,第二部分是如何获得完整的原始数组以及从第二个数组,但不改变对象。
这是我的代码,如您所见,我正在显式分配 {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"
}
]
期望的结果:
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"
}
]
您可以通过在脏位置上使用 find
来实现,returns 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²),所以当两个数组都很大时,在每个.map()
迭代中执行.find()
可能变得太昂贵了。在这种情况下,最好先将 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()
操作在大多数实现中 near-constant 及时。
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
构造函数可以采用 key/value 对数组(也是数组)。这个新 Map 作为可选的 thisArg
传递给 .map()
,以便它可以在回调中用 this
引用。
这应该匹配为 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);
过滤数组在这里被问了很多,但是 none 我找到的问题和答案考虑了我需要的 2 个条件:
1. 不改变对象。
2. 使用es6(ecmascript2015)及以上版本
3. 获取一个新数组,其中包含覆盖的对象和值。
我的问题的一部分实际上有一个答案,那就是如何过滤,但感觉像是一个 hack 而不是真正的解决方案,第二部分是如何获得完整的原始数组以及从第二个数组,但不改变对象。
这是我的代码,如您所见,我正在显式分配 {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"
}
]
期望的结果:
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"
}
]
您可以通过在脏位置上使用 find
来实现,returns 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²),所以当两个数组都很大时,在每个.map()
迭代中执行.find()
可能变得太昂贵了。在这种情况下,最好先将 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()
操作在大多数实现中 near-constant 及时。
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
构造函数可以采用 key/value 对数组(也是数组)。这个新 Map 作为可选的 thisArg
传递给 .map()
,以便它可以在回调中用 this
引用。
这应该匹配为 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);