根据部分重复项连接行

时间:2016-11-25 10:24:59

标签: javascript arrays sorting concatenation concat

我正在寻找一种更有效的方法来连接基于2个字段中重复的数组成员,理想情况下不使用循环内的循环。

数组已按nameemail升序排序 - 如果两行具有相同的nameemail,我想“合并“这些行合并为一行,第一行的drink字段变为drink_1,第二行的drink字段变为drink_2

输入

[
  {name: 'bob',  email: 'bob@bob.com',  drink: 'beer'},
  {name: 'bobs_alias', email: 'bob@bob.com',  drink: 'beer'},
  {name: 'john',  email: 'john@john.com',  drink: 'beer'},
  {name: 'john',  email: 'john@john.com',  drink: 'cider'},
  {name: 'mike',  email: 'mike@mike.com',  drink: 'wine'},
  {name: 'mike',  email: 'mike@mike.com',  drink: 'water'}
]

期望的输出

[
  { name: 'bob', email: 'bob@bob.com', drink: 'beer'},
  { name: 'bobs_alias', email: 'bob@bob.com', drink: 'beer'},
  { name: 'john', email: 'john@john.com', drink_1: 'beer', drink_2: 'cider'},
  { name: 'mike', email: 'mike@mike.com', drink_1: 'wine', drink_2: 'water'}
]

4 个答案:

答案 0 :(得分:1)

使用Array.prototype.reducehash table来获取所需的结果 - 因为它使用哈希表,即使没有已排序的输入,此提案也可以

见下面的演示:

var array=[{name:'bob',email:'bob@bob.com',drink:'beer'},{name:'bobs_alias',email:'bob@bob.com',drink:'beer'},{name:'john',email:'john@john.com',drink:'beer'},{name:'john',email:'john@john.com',drink:'cider'},{name:'mike',email:'mike@mike.com',drink:'wine'},{name:'mike',email:'mike@mike.com',drink:'water'}];

var result = array.reduce(function(hash) {
  return function(p, c) {
    let key = `${c.name}_${c.email}`;
    if (hash[key]) {
      if (hash[key].drink) {
        hash[key]['drink_' + ++hash[key + '_num']] = hash[key].drink;
        delete hash[key].drink;
      }
      hash[key]['drink_' + ++hash[key + '_num']] = c.drink;
    } else {
      hash[key] = c;
      hash[key + '_num'] = 0;
      p.push(hash[key]);
    }
    return p;
  };
}(Object.create(null)), []);

console.log(result);
.as-console-wrapper {top: 0;max-height: 100%!important;}

答案 1 :(得分:0)

您可以尝试这样的事情:



var d = [{name: "bob", email: "bob@bob.com", drink: "beer"},
{name: "bobs_alias", email: "bob@bob.com", drink: "beer"},
{name: "john", email: "john@john.com", drink: "beer"},
{name: "john", email: "john@john.com", drink: "cider"},
{name: "john", email: "john@john.com", drink: "wine"},
{name: "mike", email: "mike@mike.com", drink: "wine"},
{name: "mike", email: "mike@mike.com", drink: "water"}];

var r = [];
d.sort(function(a, b) {
  return a.name > b.name ? 1 : a.name < b.name ? -1 : 0;
}).reduce(function(p, c) {
  if (p.name === c.name && p.email === c.email) {
    var index = Object.keys(p).reduce(function(i, k) {
      var str = k.replace('drink_', '');
      if (!isNaN(str)) i = Math.max(+str, i) + 1;
      return i;
    }, 1);
    if (p.drink) {
      p['drink_' + index++] = p.drink;
    }
    p['drink_' + index] = c.drink;
    delete p.drink;
    return p;
  } else {
    r.push(c)
    return c;
  }
})

console.log(r)
&#13;
&#13;
&#13;

答案 2 :(得分:0)

使用map()filter()的组合,我们可以完成此任务。 试试这个:

console.clear();
var ps = [
  {name: 'bob',  email: 'bob@bob.com',  drink: 'beer'},
  {name: 'bobs_alias', email: 'bob@bob.com',  drink: 'beer'},
  {name: 'john',  email: 'john@john.com',  drink: 'beer'},
  {name: 'john',  email: 'john@john.com',  drink: 'cider'},
  {name: 'mike',  email: 'mike@mike.com',  drink: 'wine'},
  {name: 'mike',  email: 'mike@mike.com',  drink: 'water'}
]

var temp = [], n = 1, obj = {};
var x = ps.map(function(el, i) {
  var t = el.name + el.email;
  if(t !== temp[0]) {
    temp[0] = t;
    n = 1;
    obj = null;
    return el;
  } else {    
    obj = ps[i-1];
    obj['drink_' + n] = obj['drink'];
    delete obj['drink'];
    obj['drink_' + (n + 1)] = el['drink'];    
    n++;
    return null;
  }
})

//filter null value from array element
var y = x.filter(function(el,i){
  return el !== null;
})

//print in console
y.forEach(function(e) {console.log(e);})

答案 3 :(得分:0)

通常情况下,我是使用某种散列的粉丝,但由于数组已经排序,因此可以简单地向前看每个条目:

&#13;
&#13;
var arr=[{name:'bob',email:'bob@bob.com',drink:'beer'},{name:'bobs_alias',email:'bob@bob.com',drink:'beer'},{name:'john',email:'john@john.com',drink:'beer'},{name:'john',email:'john@john.com',drink:'cider'},{name:'mike',email:'mike@mike.com',drink:'wine'},{name:'mike',email:'mike@mike.com',drink:'water'}];


for(let i=0; i <  arr.length; i++)
	for(let j =i +1, ind = 2; j<  arr.length && arr[i].name === arr[j].name && arr[i].email === arr[j].email; j++){  	
    	if(arr[i].drink){
      	  arr[i].drink_1 = arr[i].drink;
          delete arr[i].drink;
      }
    	arr[i]['drink_' + ind++] = arr.splice(j--,1)[0].drink;
    }  
  
console.log(arr);
&#13;
&#13;
&#13;