10

因此,在搜索了几个小时的 interwebz 之后,我还没有找到我正在寻找的解决方案。

我有两个数组,其中包含包含大量信息的游戏对象。(例如标题、标签、缩略图、摘要、流派、发布日期...)。

数组 1是与注册期间指定的用户兴趣相匹配的对象的集合。

Array 2是一组与相似用户购买的游戏相匹配的对象。(相似用户是有共同兴趣的用户)

问题:有可能,在我的情况下发生了什么,有两个相同的游戏 - 阵列 1 中的游戏也在阵列 2 中。在第一个阵列中,游戏存在,因为它符合用户的兴趣。在第二个数组中,游戏存在是因为类似的用户购买了该游戏。

问题:Underscore.js 有一个不错的小函数 union() http://underscorejs.org/#union,它为您提供两个数组的联合,但它不适用于对象数组,仅适用于原始值。我怎样才能让它工作给我一个对象数组的联合?

4

9 回答 9

20

你可以很容易地实现你自己的。在这种情况下,我们将函数设为泛型,以便它可以获取任何数据类型的数组,并使用提供的比较器函数将它们合并。

// arr1 and arr2 are arrays of any length; equalityFunc is a function which
// can compare two items and return true if they're equal and false otherwise
function arrayUnion(arr1, arr2, equalityFunc) {
    var union = arr1.concat(arr2);

    for (var i = 0; i < union.length; i++) {
        for (var j = i+1; j < union.length; j++) {
            if (equalityFunc(union[i], union[j])) {
                union.splice(j, 1);
                j--;
            }
        }
    }

    return union;
}

function areGamesEqual(g1, g2) {
    return g1.title === g2.title;
}

// Function call example
arrayUnion(arr1, arr2, areGamesEqual);

有关各种对象比较实现,请参阅JavaScript中的对象比较。

于 2012-11-10T04:12:31.490 回答
5

您可以使用下划线的方式来做到这一点:

// collectionUnion(*arrays, iteratee)
function collectionUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

它只是对原始函数的改进,在_.union(*arrays)工作集合(对象数组)中添加了一个迭代对象。

这里如何使用它:

var result = collectionUnion(a, b, c, function (item) {
    return item.id;
});

仅使用数组的原始函数如下所示:

_.union = function() {
  return _.uniq(flatten(arguments, true, true));
};

还有一个完整的例子:

// collectionUnion(*arrays, iteratee)
function collectionUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

var a = [{id: 0}, {id: 1}, {id: 2}];
var b = [{id: 2}, {id: 3}];
var c = [{id: 0}, {id: 1}, {id: 2}];

var result = collectionUnion(a, b, c, function (item) {
    return item.id;
});

console.log(result); // [ { id: 0 }, { id: 1 }, { id: 2 }, { id: 3 } ]
于 2015-06-26T11:02:28.083 回答
3

Set (ES6/ES2015) 会帮助你。

const info1 = {id: 1}
const info2 = {id: 2}
const info3 = {id: 3}

const array1 = [info1, info2]
const array2 = [info1, info3]

const union = [...new Set([...array1, ...array2])]

console.log(union)

于 2016-12-30T16:21:32.567 回答
1

jQuery有方法extend

$.extend(true, object1, object2);
于 2012-11-10T04:37:45.337 回答
1

使用下划线扩展,您可以:

var objects = [{ bar : 1, nuts : 2} , {foo : 3, nuts : 4}]
_.extend.apply(this,objects)

如果列表可以为空,请确保向其附加一个空对象。

于 2013-09-17T01:04:47.070 回答
1

这是更好的解决方案

function arrayUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

var a = [{id: 0}, {id: 1}, {id: 2}];
var b = [{id: 2}, {id: 3}];
var c = [{id: 0}, {id: 1}, {id: 2}];

var result = arrayUnion(a, b, c, function (item) {
    return item.id;
});

console.log(result); 
于 2018-09-11T05:26:52.503 回答
0

使用 set 函数在 typescript 中很容易做到这一点。

const firstArr = [
    {
        id: '1',
        winner: 'Captain America',
    },
    {
        id: '4',
        winner: 'Aquaman',
    },
    {
        id: '2',
        winner: 'Captain America',
    },
    {
        id: '3',
        winner: 'Aquaman',
    },
]

const secondArr = [
    {
        id: '1',
        winner: 'Wonder women',
    },
    {
        id: '2',
        winner: 'Param',
        strenths: ['fly', 'fight', 'speed'],
    },
]
const mergedArray = [...secondArr, ...firstArr]

let set = new Set()
let unionArray = mergedArray.filter((item) => {
    if (!set.has(item.id)) {
        set.add(item.id)
        return true
    }
    return false
}, set)
 
console.log(unionArray);

于 2020-12-16T19:52:09.833 回答
0

const a=[
  {
    id:1,
    label:"mnbmnbm1"
  },
  {
    id:2,
    label:"mnbmnbm2"
  },
  {
    id:3,
    label:"mnbmnbm3"
  }
];
const b=[
  {
    id:1,
    label:"mnbmnbm1"
  },
  {
    id:2,
    label:"mnbmnbm2"
  },
  {
    id:4,
    label:"mnbmnbm5"
  }
];
const c=[
  {
    id:1,
    label:"mnbmnbm1"
  },
  {
    id:5,
    label:"mnbmnbm5"
  },
  {
    id:6,
    label:"mnbmnbm6"
  }
];

function arrayUnion(...args){
  return arrayUnique(flatten(...args));
}

function flatten(...args){
  return args.reduce((acc,cur)=>{
     if(Array.isArray(acc) && Array.isArray(cur)){
        acc=[...acc,...cur];
        return acc;
     }
  });
}

function arrayUnique(arr){
    let map={};
    
    return arr.filter(obj =>{
      let objID=obj.id;
      
      if(!map[objID]){
        map[objID]=true;
        return obj;
      }
    });
}

console.log("result",arrayUnion(a,b,c));

于 2021-01-08T07:58:25.770 回答
0

您可以使用flatSet

const union = (...arr) => [...new Set(arr.flat())];

console.log(union([1, 2], [2, 3], [3]));

于 2021-03-16T18:27:07.253 回答