过滤器独特和使用阵列复制对象下划线(Filter unique & duplicate object

2019-10-20 08:00发布

我有对象的数组:

data = [{"origin":"SJU","dest":"JFK","rank":48},{"origin":"JFK","dest":"SJU","rank":21},{"origin":"IAD","dest":"LAX","rank":31},{"origin":"LAS","dest":"SJU","rank":21}]

我想,以提取“原点”和“目标”的所有副本和独特的对象。 因此,这2是相同的,忽略了排名的关键

  • {origin:'JFK',dest:'SJU',rank:21}
  • {"origin":"SJU","dest":"JFK","rank":48}

基本上我想要2个独立的阵列:

duplicates=[{"origin":"SJU","dest":"JFK","rank":48},{"origin":"JFK","dest":"SJU","rank":21}]

unique = [{"origin":"IAD","dest":"LAX","rank":31},{"origin":"LAS","dest":"SJU","rank":21}]

使用下划线,我能扔东西像这样一起。 但似乎效率低下,只返回重复的数组:

duplicates = _.chain(data).map(function (d) {
    var ar = [d.origin, d.dest];
    return ar.sort();
}).sortBy(function (d) {
    return d
}).groupBy(function (d) {return d}).map(function (d) {
    if (d.length > 1) {
        return d[0]
    }
}).compact().value()
single = _.chain(data).map(function (d) {
    var ar = [d.origin, d.dest];
    return ar.sort();
}).sortBy(function (d) {
    return d
}).groupBy(function (d) {
    return d
}).map(function (d) {
    if (d.length == 1) {
        return d[0]
    }
}).compact().value()

我不禁感到有一种更简单的方法来得到这个。

Answer 1:

这可能是更容易引入一个临时变量来保存组:

var data = [{"origin":"SJU","dest":"JFK","rank":48},{"origin":"JFK","dest":"SJU","rank":21},{"origin":"IAD","dest":"LAX","rank":31},{"origin":"LAS","dest":"SJU","rank":21}]

var groups = _.groupBy(data, function(item) {
  return [item.origin, item.dest].sort();
});

然后:

var duplicates = [],
singles = [];

_.each(groups, function(group) {
  if (group.length > 1) {
    duplicates.push.apply(duplicates, group);
  } else {
    singles.push(group[0]);
  }
});

演示



Answer 2:

我不明白你的代码。 但是我得到了这个问题。

我看到它的方式是2个步骤:

  • 识别重复和在阵列中重复推动它们
  • 通过复制inital阵列创建uniquearray并删除所有匹配重复数组的元素。

也许它具有较低的性能,但它可能是更清晰。



Answer 3:

下面是使用普通的JavaScript的算法。 它可能不是最有效的,如果你将有成千上万的记录,但它得到是工作完成的。

var data = [
    {"origin": "SJU", "dest": "JFK", "rank":48},
    {"origin": "JFK", "dest": "SJU", "rank":21},
    {"origin": "IAD", "dest": "LAX", "rank":31},
    {"origin": "LAS", "dest": "SJU", "rank":21}
];

var uniques = [];
var doubles = [];

var i, j, l = data.length, origin, dest, foundDouble;

for ( i = 0; i < l; i += 1 ) {
    origin = data[i].origin;
    dest = data[i].dest;
    foundDouble = false;

    for ( j = 0; j < l; j += 1 ) {
        //skip the same row
        if ( i == j ) {
            continue;
        }

        if ( (data[j].origin == origin || data[j].origin == dest) && (data[j].dest == origin || data[j].dest == dest) ) {
            doubles.push( data[i] );
            foundDouble = true;
        }
    }

    if ( !foundDouble ) {
        uniques.push( data[i] );
    }
}

console.log( 'Uniques', uniques );
console.log( 'Doubles', doubles );


Answer 4:

有很多方法可以做到这一点,但这里有一个。 我从来没有使用下划线,但算法是非常简单的,你应该能够将其轻松转换。

var voyages = [{"origin":"SJU","dest":"JFK","rank":48},{"origin":"JFK","dest":"SJU","rank":21},{"origin":"IAD","dest":"LAX","rank":31},{"origin":"LAS","dest":"SJU","rank":21}],
    dupes = [],
    uniques = [],
    countMap = new Map(), //Map is from Harmony, but you can use a plain object
    voyageKeyOf = function (voyage) { return [voyage.origin, voyage.dest].sort().join(''); },
    uniques;

//Create a map that stores how many times every voyage keys were seen
voyages.forEach(function (voyage) {
    var key = voyageKeyOf(voyage),
        hasCount = countMap.get(key);

    if (!hasCount) countMap.set(key, 1);
    else {
        let count = countMap.get(key);
        countMap.set(key, ++count);
    }
});

voyages.forEach(function (voyage) {
    var key = voyageKeyOf(voyage),
        isUnique = countMap.get(key) == 1;

    if (isUnique) uniques.push(voyage)
    else dupes.push(voyage);
});


console.log('uniques', uniques);
console.log('dupes', dupes);


文章来源: Filter unique & duplicate objects in array using underscore