比较包含对象的两个数组

11

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

我想进行减法操作: 全部群组 - 用户群组 = 剩余群组

我正在使用AngularJS,不确定是否有帮助(也许可以使用筛选器)。

我查看了之前的问题并尝试了一些选项:

以下是我尝试过的选项:

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

这是其中一个数组:

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个回答

8

我认为您应该先将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;

这里是简化版的样例代码:http://jsfiddle.net/NLQGL/2/,可以根据需要进行调整。
我认为这是一个不错的解决方案,因为可以重复使用groupsIds对象(它似乎不经常改变)。
注意:如果需要的话,可以自由使用angular.forEach()代替Array.prototype.forEach

嘿,我还在处理这个问题。我认为我遇到了一个时间问题:我已经上传了我的服务并添加了一些注释:http://jsfiddle.net/9dz5A/1/ - Batman
我认为你的评论是一个完全不同的问题。 我不知道SPServices是什么,也不知道如何测试或调试它。 但我很确定你代码中的assignedGroups未定义。也许这是一个作用域问题? - Michał Miszczyszyn

2
你可以使用 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));
        });
    }

或者

//All the groups - user groups = groups remaining

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

只使用Angular JS

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

0
你可以尝试这个。
// .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;
}

结果

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

Json差异

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

    return result;
}

我不理解。我试图得到第三个数组,它是两个对象数组之间的差异。这个解决方案只是比较了两个数组。 - Batman

-3
如果您想过滤掉所有未使用的组,那么使用过滤器是正确的决定:
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;
}));

这里是Fiddle

有关文档,请查看MDN Array.prototype.filter

对于使用findfindIndex的未来解决方案,请参阅this精美文章。

编辑:要处理Objects,您可以轻松地调整过滤器函数并使用自定义比较器函数而不是indexOf。 这里是另一个Fiddle的情况。


我为那个案例添加了一个 Fiddle。 - Thomas Junk
你的答案是唯一一个真正有效的。我只是有点难以理解它。明天我会查看文档,或许会有所帮助。谢谢。 - Batman
我尝试了您的解决方案,但编辑了组以反映我的数据建模方式。不幸的是它没有起作用。http://jsfiddle.net/UDaUG/6/ - Batman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接