【问题标题】:Create a computed JSON array in JS with multiple variables在 JS 中创建具有多个变量的计算 JSON 数组
【发布时间】:2021-12-07 09:57:14
【问题描述】:

首先,如果这通常是一件简单的事情,我深表歉意,但我在 JS 方面并不是特别有经验。我正在尝试在 Plotly.js 中为当前保存原始 JSON 的工作站点制作一些图表。我们有一个 JSON 格式:

stuff = [{"name": "shark", "location": "somewhere", "number":10},
         {"name": "shark", "location": "somewhereelse", "number":50},
         {"name": "shark", "location": "somewhere", "number":25},
         {"name": "turtle", "location": "anotherplace", "number":1},
         {"name": "elephant", "location": "greatplace", "number":50},
         {"name": "elephant", "location": "greatplace", "number":75}

我需要结果看起来像:

computed = [{"name":"shark", "location":"somewhere", "number":35},
            {"name":"shark", "location":"somewhereelse", "number":50},
            {"name":"turtle", "location":"anotherplace", "number":1},
            {"name":"elephant", "location":"greatplace", "number":125}

所有名称都按位置分组,并且该组中的所有数字相加。然后,我将使用这个计算得到的 JSON 与 Plotly.js 一起绘制我已经构建的一些函数。

我想我可以将问题简化为:

forEach((item) => {
x.push(item['location']
y.push(y += stuff.number where stuff.location === x[-1])
}

但这也意味着我将获得与 stuff 中相同的行数,只是计算和绘制。恐怕我想不通了。

任何帮助将不胜感激。

【问题讨论】:

  • 请注意,如果您看到myVariable = [{",数据是一个JS对象,而不是JSON。

标签: javascript json


【解决方案1】:

只需循环出原始数组,然后将元素添加到新数组中,除非它们已经添加,或者只是添加 number 将是这里的技巧。这是定义的:

var computed: any = [];

for(var element of stuff){
  let computedElement = computed.find((ele: { location: string; }) => ele.location == element.location);
  if (computedElement){
    computedElement.number += element.number; 
  }
  else{
    computed.push(element);
  }
}

【讨论】:

    【解决方案2】:

    首先,json 以 {} 而不是 [] 开头。您的对象是一个 javascript 对象。我在下面做了一个很长的函数:

    const stuffList = [
    {"name": "shark", "location": "somewhere", "number":10},
      {"name": "shark", "location": "somewhereelse", "number":50},
      {"name": "shark", "location": "somewhere", "number":25},
      {"name": "turtle", "location": "anotherplace", "number":1},
      {"name": "elephant", "location": "greatplace", "number":50},
      {"name": "elephant", "location": "greatplace", "number":75}
    ]
    
    //extract all available location
    const locations = stuffList.map( stuffItem => {
      return stuffItem.location
    })
    
    const filteredStuff = locations.map( location => {
      const number= stuffList.map( stuffItem => {
          if(stuffItem.location === location) {
            return stuffItem.number
          }
          return 0
      }).reduce( (a, b) => a + b)// total all the numbers of mathcing 
      location
      
      //get the first newStuffItem value equals to location 
      const [filteredStuffItem] = stuffList.map( stuffItem => {
        if(stuffItem.location === location) {
          return {
            name: stuffItem.name,
            location,
            number
          }
        }
      }).filter( stuffItem => {
        return stuffItem?.location === location
      })
    
      return filteredStuffItem
    })
    
    const newStuffList = filteredStuff.filter((thing, index) => {
      const _thing = JSON.stringify(thing);
      return index === filteredStuff.findIndex(obj => {
        return JSON.stringify(obj) === _thing;
      })
    });
    
    console.log(newStuffList)
    

    或者 Deepak 在 javascript 中的魔法:

    const stuff = [
      {"name": "shark", "location": "somewhere", "number":10},
      {"name": "shark", "location": "somewhereelse", "number":50},
      {"name": "shark", "location": "somewhere", "number":25},
      {"name": "turtle", "location": "anotherplace", "number":1},
      {"name": "elephant", "location": "greatplace", "number":50},
      {"name": "elephant", "location": "greatplace", "number":75}
    ]
    
    var computed = [];
    
    for(var element of stuff){
      let computedElement = computed.find((ele) => ele.location == element.location);
      if (computedElement){
        computedElement.number += element.number; 
      }
      else{
        computed.push(element);
      }
    }
    
    console.log(computed)
    

    【讨论】:

      【解决方案3】:

      很抱歉没有尽快回复,感谢评论的人。无论出于何种原因,我无法让其他建议的解决方案发挥作用,但我看到了对所需逻辑的另一种看法,帮助我弄清楚了。

      if (!label.includes(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])) {
          label.push(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])
          x.push(item['date'])
          y.push(item['sum'])
      } else {
          var indx = label.indexOf(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])
          let summed = y[indx] + item['sum']
          y.splice(indx, 1, summed)
      

      所以本质上这创建了类似于复合键的东西,并推送初始数据以将其添加到标签列表,然后将数据添加到相关列表。如果该复合键再次出现,则该值将使用 splice 方法更新。

      唯一的问题是,由于这些列表与输入到它们的数据没有任何关联,因此很少有正确的标签和数据不匹配的机会,但经过大量测试后,我已经整理出来了确实有效。

      再次感谢之前提供帮助的评论者。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-31
        • 2019-04-16
        • 1970-01-01
        • 1970-01-01
        • 2021-01-27
        • 2013-03-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多