简体   繁体   English

比较两个 arrays 并基于具有不同对象的合并数组进行合并的问题

[英]Issue with comparing two arrays and merging based on the merged array with distinct objects

Initially the array $scope.distinctCourseUsers will be empty, after every dynamic new response I would be appending all the objects to the previous list including new set of objects and then eliminating the duplicates of an array by using reduce method and storing back to $scope.distinctCourseUsers最初,数组$scope.distinctCourseUsers将为空,在每个动态新响应之后,我会将所有对象附加到前一个列表中,包括新的对象集,然后使用 reduce 方法消除数组的重复项并将其存储回$scope.distinctCourseUsers

$scope.courseUsers = response;
Array.prototype.push.apply($scope.distinctCourseUsers,response); 
distinctCourseUsers = result = $scope.distinctCourseUsers.reduce((unique, o) => {
    if(!unique.some(obj => obj.Id === o.Id )) {
    unique.push(o);
    }
    return unique;
},[]);

$scope.courseUsers = response;

For the I response two new array objects will be stored into $scope.courseUsers对于 I 响应,两个新的数组对象将存储到$scope.courseUsers

console.log($scope.courseUsers);

(2) [{…}, {…}]
0: {Id: 22410, Name: "test01", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
1: {Id: 22411, Name: "test02", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}

Merging the empty $scope.distinctCourseUsers array with the response stored in $scope.courseUsers将空的$scope.distinctCourseUsers数组与存储在$scope.courseUsers中的响应合并

Array.prototype.push.apply($scope.distinctCourseUsers,response); 
console.log($scope.distinctCourseUsers);

For the II response there will be two new objects, so appending previous Array List(2) + (New Array List(2) + Previous Array List(4)) Totally (2+2+4=6) to the $scope.distinctCourseUsers array list对于 II 响应,将有两个新对象,因此将 previous Array List(2) + (New Array List(2) + Previous Array List(4)) Totally (2+2+4=6) 附加到$scope.distinctCourseUsers数组列表

(4) [{…}, {…}, {…}, {…}]
0: {Id: 22410, Name: "test01", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
1: {Id: 22411, Name: "test02", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
2: {Id: 22410, Name: "test01", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
3: {Id: 22411, Name: "test02", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
4: {Id: 22412, Name: "test03", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
5: {Id: 22413, Name: "test04", RoleType: "End user", IsEnrolled: false, EnrolledOn: "", …}

// The below reduce opertator will eliminate all the redundant objects
distinctCourseUsers = result = $scope.distinctCourseUsers.reduce((unique, o) => {
    if(!unique.some(obj => obj.Id === o.Id )) {
    unique.push(o);
    }
    return unique;
},[]);


console.log(distinctCourseUsers);

Actual & Expected Result:实际和预期结果:

0: {Id: 22410, Name: "test01", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
1: {Id: 22411, Name: "test02", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
2: {Id: 22412, Name: "test03", RoleType: "XL Teacher", IsEnrolled: false, EnrolledOn: "", …}
3: {Id: 22413, Name: "test04", RoleType: "End user", IsEnrolled: false, EnrolledOn: "", …}

The above approach is inefficient, due to performance overhead associated with appending previous list of objects.由于与附加先前的对象列表相关的性能开销,上述方法效率低下。 Is it possible to eliminate the duplicate at the first place mentioned in below code是否可以在下面代码中提到的第一个位置消除重复项

Array.prototype.push.apply($scope.distinctCourseUsers,response); 

How would you reduce the code to make it efficient enough to get the above result?您将如何减少代码以使其足够高效以获得上述结果?

Actually did a blog post on this recently , and it's dead simple.实际上最近在这方面做了一篇博客文章,而且很简单。 I have several options for you here, so make sure you get to the end.我在这里为您提供了多种选择,因此请确保您完成了。

You can use Array s and a Set to get unique items.您可以使用ArraySet来获取唯一项目。 Here's the basic idea using simple values.这是使用简单值的基本思想。

const arr = [19,22,7,12,6,85];
const arr2 = [22,8,3,19,45];
const newArr = [...arr, ...arr2];
// newArr equals [19, 22, 7, 12, 6, 85, 22, 8, 3, 19, 45]
const uniqueArr =  = Array.from(new Set(newArr));
// uniqueArr equals [19, 22, 7, 12, 6, 85, 8, 3, 45]

It is important to remember that objects are by ref, so if you have two objects that look the same (structurally) that doesn't mean they are the 'same', so think about that when using a Set.重要的是要记住对象是按引用的,所以如果你有两个看起来相同(结构上)的对象并不意味着它们是“相同的”,所以在使用 Set 时要考虑这一点。 However, if the objects were pushed to each array by ref, then this should still work for you.但是,如果对象被 ref 推送到每个数组,那么这仍然对您有用。 If object ref is in question (at all) then you might want an intermediary.如果 object ref 有问题(完全有问题),那么您可能需要一个中介。

const intermediary = [...myTrueVar];
intermediary.push(myObj);
const keys = itermediary.map((it) => it.key));
const uniqueKeys = Array.from(new Set(keys));
myTrueVar = intermediary.filter((it) => uniqueKeys.includes(it.key))

Or, you could get really crazy或者,你可能会变得非常疯狂

const intermediary = [...myTrueVar];
intermediary.push(myObj)
const stringed = intermediary.map((it) => JSON.stringify(it));
myTrueVar = Array.from(new Set(stringed)).map((it) => JSON.parse(it));

But that's probably overkill, and probably assumes the object keys are always in the same order, so the first bit intermediary is probably the better option (and probably less overhead).但这可能是矫枉过正,并且可能假设 object 密钥始终处于相同的顺序,因此第一位中介可能是更好的选择(并且可能开销更少)。

Also remember that, while the Set constructor is supported by IE 11, Array.from is not (and deconstruction even less so), so if you're stuck in the past you'll need to transpile it down with Babel.还要记住,虽然 IE 11 支持Set构造函数, Array.from不支持(而且解构更不支持),所以如果你被困在过去,你需要用 Babel 将它转换下来。

Or , you could just simply check your initial array for the item and conditionally add it when necessary.或者,您可以简单地检查项目的初始数组并在必要时有条件地添加它。 Probably the most performant, since your only adding one user at a time.可能是性能最高的,因为您一次只添加一个用户。

!$scope.distinctCourseUsers.find((user) => user.Id === response.Id) &&
  $scope.distinctCourseUsers.push(response)

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

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