比较两个包含对象的数组

时间:2022-01-29 12:13:32

I have two arrays which only contain objects for groups. One contains all the groups on my site. The other contains all the groups a specific user belongs to.

我有两个数组,只包含组的对象。一个包含我网站上的所有组。另一个包含特定用户所属的所有组。

I'd like to subtract: All the groups - user groups = groups remaining

我想减去:所有组 - 用户组=剩余的组

I'm using AngularJS, I'm not sure if that helps here or not (maybe a filter could be used).

我正在使用AngularJS,我不确定这是否有帮助(可能会使用过滤器)。

I looked at previous questions and came across some options:

我查看了以前的问题并遇到了一些选择:

These are the ones I tried:

这些是我试过的:

$scope.availableGroups =  $($scope.groups).not($scope.assignedGroups).get();
$scope.availableGroups = $.grep($scope.groups,function(x) {return $.inArray(x, $scope.assignedGroups) < 0})

This is one of the arrays:

这是一个数组:

assignedGroups:

assignedGroups:

[{
    id: 115,
    name: 'Test Group 2',
    Description: '',
    owner: 10,
    OwnerIsUser: false,
}, {
    id: 116,
    name: 'Test Group 3',
    Description: '',
    owner: 71,
    OwnerIsUser: false,
}, {
    id: 117,
    name: 'Test Group 4',
    Description: '',
    owner: 71,
    OwnerIsUser: false,
}, {
    id: 118,
    name: 'Test Group 5',
    Description: '',
    owner: 115,
    OwnerIsUser: false,
}, {
    id: 119,
    name: 'Test Group 6',
    Description: '',
    owner: 8,
    OwnerIsUser: true,
}];

4 个解决方案

#1


8  

I think you should extract ids to an object first and then compare two objects. Eg:

我认为你应该首先将id提取到一个对象然后比较两个对象。例如:

var assignedGroupsIds = {};
var groupsIds = {};
var result = [];

$scope.assignedGroups.forEach(function (el, i) {
  assignedGroupsIds[el.id] = $scope.assignedGroups[i];
});

$scope.groups.forEach(function (el, i) {
  groupsIds[el.id] = $scope.groups[i];
});

for (var i in groupsIds) {
    if (!assignedGroupsIds.hasOwnProperty(i)) {
        result.push(groupsIds[i]);
    }
}

return result;

Here goes simplified fiddle: http://jsfiddle.net/NLQGL/2/ Adjust it to your needs.

这里简化了小提琴:http://jsfiddle.net/NLQGL/2/根据您的需要调整它。

I think it's a good solution since you could reuse the groupsIds object (it seems not to change often).

我认为这是一个很好的解决方案,因为你可以重用groupsIds对象(似乎不经常改变)。

Note: Feel free to use angular.forEach() instead of Array.prototype.forEach

注意:可以随意使用angular.forEach()而不是Array.prototype.forEach

#2


2  

You can use a combination of Angular JS's $filter service and Lo-dash's findWhere method to get unique objects in two arrays, try this :

你可以结合使用Angular JS的$ filter服务和Lo-dash的findWhere方法来获取两个数组中的唯一对象,试试这个:

// When you don't know the lengths of the arrays you want to compare
    var allTheGroupsLength = allTheGroups.length;
    var userGroupsLength = userGroups.length;
    var groupsRemaining = [];

    if(allTheGroupsLength > userGroupsLength){
        getDifference(allTheGroups, userGroups);
    }
    else{
        getDifference(userGroups, allTheGroups);
    }

    function getDifference(obj1, obj2){
        groupsRemaining  = $filter('filter')(obj1, function(obj1Value){
              return !Boolean(_.findWhere(obj2, obj1Value));
        });
    }

OR

要么

//All the groups - user groups = groups remaining

 groupsRemaining  = $filter('filter')(allTheGroups, function(allTheGroupsObj){
                  return !Boolean(_.findWhere(userGroups, allTheGroupsObj));
              });

Using only Angular JS

仅使用Angular JS

  groupsRemaining =  $filter('filter')(allTheGroups, function(allTheGroupsObj){
                      return !angular.equals(allTheGroupsObj, $filter('filter')(userGroups, function(userGroupsObj){
                      return angular.equals(allTheGroupsObj,userGroupsObj);})[0]);
                  });

#3


0  

You can try this

你可以试试这个

// .compare method to Array's prototype to call it on any array
Array.prototype.compare = function (array) 
{
    if (!array)
        return false;

    // compare lengths
    if (this.length != array.length)
        return false;

    for (var i = 0, l = this.length; i < l; i++)
    {
        if (this[i] instanceof Array && array[i] instanceof Array) 
        {
           if (!this[i].compare(array[i]))
              return false;
        }
        else if (this[i] != array[i])
        {
            return false;
        }
    }
    return true;
}

Result

结果

[1, 2, [3, 4]].compare([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].compare([1, 2, 1, 2]) === true;

Json Diff

Json Diff

function diff(obj1, obj2)
 {
    var result = {};
    $.each(obj1, function (key, value)
    {
        if (!obj2.hasOwnProperty(key) || obj2[key] !== obj1[key])
        {
            result[key] = value;
        }
    });

    return result;
}

#4


-3  

(maybe a filter could be used).

(也许可以使用过滤器)。

If you want to filter out all unused groups, a filter is the right decision:

如果您想过滤掉所有未使用的组,过滤器是正确的决定:

var groups=["admin","moderator","reader","writer"]

var user={
   name:"the user",
   groups:["reader", "writer"]
};

console.log(groups.filter(function(group){
    if (user.groups.indexOf(group)==-1) return true;
}));

Here is the Fiddle.

这是小提琴。

For the documentation take a loog at MDN Array.prototype.filter

对于文档,请在MDN Array.prototype.filter上获取一个loog

For a future solution with find or findIndex take a look at this fine article.

有了find或findIndex的未来解决方案,请看一下这篇精彩的文章。

Edit: For dealing with Objects you could easily adapt the filter function and use a custom comparator function instead indexOf. Here another Fiddle for that case.

编辑:对于处理对象,您可以轻松地调整过滤器功能并使用自定义比较器功能而不是indexOf。这是另一个小提琴。

#1


8  

I think you should extract ids to an object first and then compare two objects. Eg:

我认为你应该首先将id提取到一个对象然后比较两个对象。例如:

var assignedGroupsIds = {};
var groupsIds = {};
var result = [];

$scope.assignedGroups.forEach(function (el, i) {
  assignedGroupsIds[el.id] = $scope.assignedGroups[i];
});

$scope.groups.forEach(function (el, i) {
  groupsIds[el.id] = $scope.groups[i];
});

for (var i in groupsIds) {
    if (!assignedGroupsIds.hasOwnProperty(i)) {
        result.push(groupsIds[i]);
    }
}

return result;

Here goes simplified fiddle: http://jsfiddle.net/NLQGL/2/ Adjust it to your needs.

这里简化了小提琴:http://jsfiddle.net/NLQGL/2/根据您的需要调整它。

I think it's a good solution since you could reuse the groupsIds object (it seems not to change often).

我认为这是一个很好的解决方案,因为你可以重用groupsIds对象(似乎不经常改变)。

Note: Feel free to use angular.forEach() instead of Array.prototype.forEach

注意:可以随意使用angular.forEach()而不是Array.prototype.forEach

#2


2  

You can use a combination of Angular JS's $filter service and Lo-dash's findWhere method to get unique objects in two arrays, try this :

你可以结合使用Angular JS的$ filter服务和Lo-dash的findWhere方法来获取两个数组中的唯一对象,试试这个:

// When you don't know the lengths of the arrays you want to compare
    var allTheGroupsLength = allTheGroups.length;
    var userGroupsLength = userGroups.length;
    var groupsRemaining = [];

    if(allTheGroupsLength > userGroupsLength){
        getDifference(allTheGroups, userGroups);
    }
    else{
        getDifference(userGroups, allTheGroups);
    }

    function getDifference(obj1, obj2){
        groupsRemaining  = $filter('filter')(obj1, function(obj1Value){
              return !Boolean(_.findWhere(obj2, obj1Value));
        });
    }

OR

要么

//All the groups - user groups = groups remaining

 groupsRemaining  = $filter('filter')(allTheGroups, function(allTheGroupsObj){
                  return !Boolean(_.findWhere(userGroups, allTheGroupsObj));
              });

Using only Angular JS

仅使用Angular JS

  groupsRemaining =  $filter('filter')(allTheGroups, function(allTheGroupsObj){
                      return !angular.equals(allTheGroupsObj, $filter('filter')(userGroups, function(userGroupsObj){
                      return angular.equals(allTheGroupsObj,userGroupsObj);})[0]);
                  });

#3


0  

You can try this

你可以试试这个

// .compare method to Array's prototype to call it on any array
Array.prototype.compare = function (array) 
{
    if (!array)
        return false;

    // compare lengths
    if (this.length != array.length)
        return false;

    for (var i = 0, l = this.length; i < l; i++)
    {
        if (this[i] instanceof Array && array[i] instanceof Array) 
        {
           if (!this[i].compare(array[i]))
              return false;
        }
        else if (this[i] != array[i])
        {
            return false;
        }
    }
    return true;
}

Result

结果

[1, 2, [3, 4]].compare([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].compare([1, 2, 1, 2]) === true;

Json Diff

Json Diff

function diff(obj1, obj2)
 {
    var result = {};
    $.each(obj1, function (key, value)
    {
        if (!obj2.hasOwnProperty(key) || obj2[key] !== obj1[key])
        {
            result[key] = value;
        }
    });

    return result;
}

#4


-3  

(maybe a filter could be used).

(也许可以使用过滤器)。

If you want to filter out all unused groups, a filter is the right decision:

如果您想过滤掉所有未使用的组,过滤器是正确的决定:

var groups=["admin","moderator","reader","writer"]

var user={
   name:"the user",
   groups:["reader", "writer"]
};

console.log(groups.filter(function(group){
    if (user.groups.indexOf(group)==-1) return true;
}));

Here is the Fiddle.

这是小提琴。

For the documentation take a loog at MDN Array.prototype.filter

对于文档,请在MDN Array.prototype.filter上获取一个loog

For a future solution with find or findIndex take a look at this fine article.

有了find或findIndex的未来解决方案,请看一下这篇精彩的文章。

Edit: For dealing with Objects you could easily adapt the filter function and use a custom comparator function instead indexOf. Here another Fiddle for that case.

编辑:对于处理对象,您可以轻松地调整过滤器功能并使用自定义比较器功能而不是indexOf。这是另一个小提琴。