【问题标题】:Javascript: how to merge two arrays by univocal key, and based on property?Javascript:如何通过单义键并基于属性合并两个数组?
【发布时间】:2016-05-02 22:32:06
【问题描述】:

我有两个数组:一个用于人员,一个用于将用户的评分和评价映射到任何人。
简单来说,是这样的:

var persons = [
  { id: '1', name: 'alice' },
  { id: '2', name: 'bob' },
  { id: '3', name: 'charlie' },
];   

var usersToPersons = [
  { userId: '1', personId: '1', hide: true },
  { userId: '1', personId: '2', hide: false },
  { userId: '7', personId: '3' },
];

我需要提取当前用户未“隐藏”的人员。
到目前为止,我已经提出了这个(工作,但很愚蠢)的功能:

function getPersonsForUser(userId) {
  var result = {};
  for (var p = 0; p < persons.length; p++) {
    for (var u = 0; u < usersToPersons.length; u++) {
      if (usersToPersons[u].userId === userId) {
        if (persons[p].id === usersToPersons[u].personId) {
          if (usersToPersons[u].hide === true) {
            console.warn('person', persons[p].name, 'skipped because this user hides it');
            break;
          } else {
            result[persons[p].id] = persons[p];
          }
        } else {
          result[persons[p].id] = persons[p];
        }
      } else {
        result[persons[p].id] = persons[p];
      }
    }
  }
  return result;
}

console.log(getPersonsForUser('1'));

结果:

person alice skipped because this user hides it
{ '2': { id: '2', name: 'bob' },
  '3': { id: '3', name: 'charlie' } }

问题是:有没有更快速/智能/流畅的方法来按用户过滤人员?

【问题讨论】:

  • 为什么你的代码返回charlie?它对应的userId不是'1'
  • 因为我想隐藏被userId '1'标记为隐藏的人;我想要所有其他人,即使是那些 userId '1' 的用户没有设置任何标志的人。
  • { userId: '7', personId: '3' }。 7 !== 1
  • 是:if (usersToPersons[u].userId === userId) { ... } else { result[persons[p].id] = persons[p]; } 即:我只想隐藏特定用户选择隐藏的人。我想获得所有其他人(无论其他用户选择了什么)。

标签: javascript node.js filtering


【解决方案1】:

看这里:Array prototype filter method

function getVisible(selUserId){
  var visiblePersons = persons.filter(function(v,i,a){
    var isThisPersonVisible = !usersToPersons.filter(function(vv,ii,aa){
      return (vv.personId === v.id && !vv.hide && vv.userId === selUserId || !vv.userId);
    }).length;

    return isThisPersonVisible;
  });

  return visiblePersons;
}

你可以在这里试试

demo

希望对你有帮助

【讨论】:

  • 这很好!不记得Array.prototype.filter()...谢谢!
【解决方案2】:

我会为此使用下划线库:

var persons = [{
  id: '1',
  name: 'alice'
}, {
  id: '2',
  name: 'bob'
}, {
  id: '3',
  name: 'charlie'
}, ];

var usersToPersons = [{
  userId: '1',
  personId: '1',
  hide: true
}, {
  userId: '1',
  personId: '2',
  hide: false
}, {
  userId: '7',
  personId: '3'
}, ];

function getPersonsForUser(userId) {
  return _.map(
    _.filter(usersToPersons,
      function(doc) {
        return doc.userId === userId && !doc.hide
      }),
    function(doc) {
      return persons[doc.personId]
    });
}

console.log(getPersonsForUser('1'))
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"&gt;&lt;/script&gt;

【讨论】:

  • 这很好,但是您的代码只返回一个对象('charlie')... :-(
【解决方案3】:

使用 ES6 会是这样的:

let getPersonsForUser = (id) => {
  let ids = usersToPersons
      .filter(user => user.userId === id && !user.hide)
      .map(user => user.personId);

  return persons.filter(person => ids.includes(person.id));
};

你可以在 ES5 中做同样的事情,但是会更冗长一些。

【讨论】:

  • 还没有 ES6,请... :-)
猜你喜欢
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
相关资源
最近更新 更多