【问题标题】:Using underscore unique on object在对象上使用唯一的下划线
【发布时间】:2014-08-19 14:33:48
【问题描述】:

我想返回房间对象相同的唯一数组。

var input = [
  {
    position:{
      room: {
        name: 'WC',
        number: '001'
      }
    }
  },
  {
    position:{
      room: {
        name: 'WC',
        number: '001'
      }
    }
  },
  {
    position:{
      room: {
        name: 'RWC',
        number: '007'
      }
    }
  }
];

所以这个列表是:

var input = [
  {
    position:{
      room: {
        name: 'WC',
        number: '001'
      }
    }
  },
  {
    position:{
      room: {
        name: 'RWC',
        number: '007'
      }
    }
  }
];

我试过了:

  var distinctRooms = _.uniq(input, function(input){
    return input.position.room
  });

但它会返回整个列表。还没有看到您比较对象的任何示例。 _uniq 有可能做到这一点吗?

【问题讨论】:

    标签: javascript underscore.js


    【解决方案1】:

    房间对象不同。如果您认为房间的数量相等,则可以使用

      var distinctRooms = _.uniq(input, function(input){
        return input.position.room.number;
      });
    

    【讨论】:

    • 即使名称不同,也会丢弃具有匹配编号的房间,这不是 OP 所要求的
    • @amenadiel 你怎么知道 OP 的房间编号相同但名称不同? :) 对我来说听起来很不寻常。
    • 这是我从小就有的礼物 ;)
    【解决方案2】:

    也许你应该看看这个answer,他在那里迭代并创建了一个具有唯一值的数组。

    【讨论】:

      【解决方案3】:

      使用提供深度对象比较的_.isEqual() function,可以创建一个函数,将其应用于对象数组并从该函数创建一个混合。

      算法:

      1. 从列表中取出第一个元素(head),将其存储在结果中
      2. 迭代列表的其余部分(tail),删除 .isEqual 到第一个元素的每个元素
      3. 如果列表的其余部分不为空,则将其传递到步骤1,否则返回结果

      代码,以递归方式实现:

      _.mixin({
          deepUniq: (function () {
              var dedup = function (coll, result) {
                  var head = _.first(coll),
                      tail = _.reject(_.rest(coll), function (curr) {
                          return _.isEqual(curr, head);
                      });
      
                  result.push(head);
                  return (tail.length) ? dedup(tail, result) : result;
              };
              return function (coll) {
                  return dedup(coll, []);
              };
          })()
      });
      

      警告:这种方法的运行时间呈指数级,即对于长的深度嵌套对象列表,它会越来越慢。我的建议是比较不同解决方案的正确性和性能。


      免责声明:此解决方案基于https://stackoverflow.com/a/19641747/

      【讨论】:

        【解决方案4】:

        只要没有循环结构,都可以使用 JSON Stringify 对每个房间属性进行深度比较

        _.uniq(input, function(input){
            return JSON.stringify(input.position.room)
          });
        

        【讨论】:

        • 非数组对象的属性不保证按任何特定顺序进行字符串化。
        • 你是对的。我想您可以提取对象键并使用 _.sort 来提供排序副本。看起来有点矫枉过正:(
        • 没有 -1 级已接受答案的徽章吗? ¬¬
        • 应该有一个用于创建 Heisenbug。 :)
        • @user1572526 请注意,您依赖于未定义的行为。 :) var isAlive = JSON.stringify({name: 1, number: 2}) === JSON.stringify({number: 2, name: 1}) - 是纯量子力学。 :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-26
        • 2012-10-20
        • 1970-01-01
        • 2014-12-06
        • 2017-03-26
        • 1970-01-01
        相关资源
        最近更新 更多