从数组中查找JSON对象的最大值并合并它们

时间:2017-07-28 18:22:45

标签: javascript jquery json underscore.js lodash

我是javascript的新手,我的JSON数组包含一些重复的键,如下所示:

var connections = [

  {
      "source":"l1",
      "target":"l2",
      "metrics": { "normal":20  },
      "metadata": { "streaming": 1 }
    },
   {
      "source":"l2",
      "target":"l3",
      "metrics": { "normal":30  },
      "metadata": { "streaming": 1 }
    },

    {
      "source":"l2",
      "target":"l3",
      "metrics": { "normal":25  },
      "metadata": { "streaming": 1 }
    },
    {
      "source":"l3",
      "target":"l4",
      "metrics": { "normal":24  },
      "metadata": { "streaming": 1 }
    },
    {
      "source":"l3",
      "target":"l4",
      "metrics": { "normal":21  },
      "metadata": { "streaming": 1 }
    },
    {
      "source":"l3",
      "target":"l4",
      "metrics": { "normal":20  },
      "metadata": { "streaming": 1 }
    },


]

现在我想要合并具有相同“source”和“target”值的重复JSON,并且键“normal”应该是所有相同源和目标的最大值。 所以给出的例子的答案是:

var answer =[
{
          "source":"l1",
          "target":"l2",
          "metrics": { "normal":20  },
          "metadata": { "streaming": 1 }
        },
       {
          "source":"l2",
          "target":"l3",
          "metrics": { "normal":30  },
          "metadata": { "streaming": 1 }
        },
        {
          "source":"l3",
          "target":"l4",
          "metrics": { "normal":24  },
          "metadata": { "streaming": 1 }
        },

] 

这只是一个用不同对象进行的示例对象。我不知道如何解决这个问题, 我认为下划线或lodash可以很容易地解决这个问题,但任何解决方案都可以接受。

3 个答案:

答案 0 :(得分:1)

使用_.groupBy()按来源和目标收集对象。使用_.map()和Array#reduce来获取每个组中具有最大normal值的那个。

var connections = [{"source":"l1","target":"l2","metrics":{"normal":20},"metadata":{"streaming":1}},{"source":"l2","target":"l3","metrics":{"normal":30},"metadata":{"streaming":1}},{"source":"l2","target":"l3","metrics":{"normal":25},"metadata":{"streaming":1}},{"source":"l3","target":"l4","metrics":{"normal":24},"metadata":{"streaming":1}},{"source":"l3","target":"l4","metrics":{"normal":21},"metadata":{"streaming":1}},{"source":"l3","target":"l4","metrics":{"normal":20},"metadata":{"streaming":1}}];

var result = _(connections)
  .groupBy(function(o) { // group by source and target
    return o.source + '-' + o.target;
  })
  .map(function(arr) { // map the groups to values
    return arr.reduce(function(max, o) { // get the object with the hight normal in each group
      return max.metrics.normal > o.metrics.normal ? max : o;
    });
  })
  .value();

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

答案 1 :(得分:1)

您可以将对象用作地图,将source + target作为关键字,将connections的对象作为值,保留每个source组合的指标最高的对象{1}} + target

var connections = [
  {"source": "l1", "target": "l2", "metrics": {"normal": 20}, "metadata": {"streaming": 1} }, 
  {"source": "l2", "target": "l3", "metrics": {"normal": 30}, "metadata": {"streaming": 1} },
  {"source": "l2", "target": "l3", "metrics": {"normal": 25}, "metadata": {"streaming": 1} }, 
  {"source": "l3", "target": "l4", "metrics": {"normal": 24}, "metadata": {"streaming": 1} }, 
  {"source": "l3", "target": "l4", "metrics": {"normal": 21}, "metadata": {"streaming": 1} }, 
  {"source": "l3", "target": "l4", "metrics": {"normal": 20}, "metadata": {"streaming": 1} }
];

var map = {};
connections.forEach((connection) => {
  var mapKey = connection.source + "/" + connection.target;
  answerConnection = map[mapKey];

  if (!answerConnection || answerConnection.metrics.normal < connection.metrics.normal)
     map[mapKey] = connection;
});

var answer = Object.values(map);

console.log(answer);

答案 2 :(得分:0)

您可以根据目标和源相同将阵列缩减为新阵列,然后检查指标是否超过以前存储的值

var connections = [
  {"source": "l1", "target": "l2", "metrics": {"normal": 20}, "metadata": {"streaming": 1} }, 
  {"source": "l2", "target": "l3", "metrics": {"normal": 30}, "metadata": {"streaming": 1} },
  {"source": "l2", "target": "l3", "metrics": {"normal": 25}, "metadata": {"streaming": 1} }, 
  {"source": "l3", "target": "l4", "metrics": {"normal": 24}, "metadata": {"streaming": 1} }, 
  {"source": "l3", "target": "l4", "metrics": {"normal": 21}, "metadata": {"streaming": 1} }, 
  {"source": "l3", "target": "l4", "metrics": {"normal": 20}, "metadata": {"streaming": 1} }
]

var res = connections.reduce( (a,b) => {
    let i = a.findIndex( item => item.target === b.target && item.source === b.source);
    if (i===-1) {
        a.push(b);
    } else if (a[i].metrics.normal < b.metrics.normal) {
        a[i] = b;
    }
    return a;
}, []);

document.body.innerHTML = '<pre>' + JSON.stringify(res,0,4) + '</pre>'