【问题标题】:Merge json entries with d3将 json 条目与 d3 合并
【发布时间】:2013-12-09 16:32:01
【问题描述】:

我正在做一些可视化,需要合并某些 json 条目。

问题是,被调用的 json 文件有点混乱。某些条目需要合并,而其他条目应保持不变。

我得到的json是这样的:

[
  {
    "label": "de",
    "visits": 80,
  },
  {
    "label": "fr",
    "visits": 80,
  },
  {
    "label": "/de",
    "visits": 80,
  },
  {
    "label": "/fr",
    "visits": 80,
  },
  {
    "label": "Aktuell",
    "visits": 80,
  },
  {
    "label": "fr/Aktuell",
    "visits": 80,
  },
  {
    "label": "index",
    "visits": 80,
  }
]

我需要的是:

[
  {
    "label": "de",
    "visits": 160,
  },
  {
    "label": "fr",
    "visits": 160,
  },
  {
    "label": "Aktuell",
    "visits": 160,
  },
  {
    "label": "index",
    "visits": 80,
  }
]

标签为“de”和“/de”以及“fr”和“/fr”或“fr/Aktuell”和“Aktuell”的条目需要合并,而其他条目应保持相同,如“索引”。

有没有办法使用 d3 做到这一点? 我想只使用javascript我必须获取json文件,然后搜索条目,创建一个新条目并将数字相加然后获取原始json,删除这些条目并添加新条目......虽然我也也不知道该怎么做。

这也不是最好的解决方案,因为我必须生成第二个必须处理的对象并减慢整个系统的速度。我们已经遇到了性能问题,我不想制造新的瓶颈。

另一个问题是,我需要能够扩展应该合并的条目列表...

有没有一种快速简单的方法来做到这一点?

我知道这似乎是一个“嘿,我太懒了,为我做”的帖子。 我可以向你保证不是。它更像是一个“我搜索过、阅读过、尝试过、发誓并哭过。现在我正在向专业人士寻求帮助”的帖子。

更新:

我不想只过滤“/”的最后一部分。这只是一个例子。过滤器会让我更喜欢:将所有 [en,EN,/en,english,anglais] 与标签 en 组合在一起。还将所有 [de, DE, /de, deutsch, German] 与标签 de 组合为一个。保留所有其他未合并的内容。

【问题讨论】:

    标签: javascript json d3.js


    【解决方案1】:

    Javascript 应该足够了:

    function clean(arr) {
        var obj = {}; 
        // obj will contain a map with keys being 'label' and value being 'visits'
        for (var i = 0; i < arr.length; i++) {
            var labelParts = arr[i].label.split('/')
            var label = labelParts[labelParts.length-1]
            // Do a bit of filtering on the label
    
            if(typeof obj[label]!=='undefined') {
                 obj[label] += arr[i].visits
            } else {
                 obj[label] = arr[i].visits
            }
         }
         return Object.keys(obj).map(function (key) { return {label:key,visits:obj[key]}; });
         // Re-create an array out of the object
    }
    

    我假设您想过滤“/”之后的最后一部分。

    jsFiddle:http://jsfiddle.net/4peN9/2/

    【讨论】:

    • 谢谢!唯一的问题是,我不想只过滤“/”的最后一部分。这只是一个例子。过滤器会让我更喜欢:将所有 [en,EN,/en,english,anglais] 与标签 en 组合在一起。还可以将所有 [de, DE, /de, deutsch, German] 与标签 de 合并为一个。保留所有其他未合并的内容。
    • 那么你只需要用你想要的更新过滤部分。我猜你可能需要一组你正在寻找的字符串。
    【解决方案2】:

    我会调查 D3 的 nest 操作。指定适当的键和汇总函数来获得您想要的应该不会太难。大意是:

    var cleanup = function(l) {
        var i = l.indexOf("/");
        return i < 0 ? l : l.substring(i+1, l.length);
    };
    var getVisits = function(d) { return d.visits; };
    var sum = function(a, b) { return a + b; };
    
    var nest = d3.nest()
        .key(function(d) { return cleanup(d.label); })
        .rollup(function(a) { return a.map(getVisits).reduce(sum); });
    

    jsFiddle:http://jsfiddle.net/4peN9/3/

    【讨论】:

      【解决方案3】:

      我现在为此编写了一个非常丑陋但功能强大的 JavaScript 脚本。我确信它可以更有效地完成,但这对我来说应该是 atm。

      它是这样的:

      function clean(arr) 
        {
          mrgLst = [
            {
              "valid": "de",
              "invalid": ["/de"]
            },
            {
              "valid": "fr",
              "invalid": ["/fr"]
            },
            {
              "valid": "en",
              "invalid": ["/en"]
            },
            {
              "valid": "it",
              "invalid": ["/it"]
            },
            {
              "valid": "/index",
              "invalid": ["/index.html"]
            }
          ]
      
          var obj = []; 
          for (var i = 0; i < mrgLst.length; i++) 
          {
            var valid = mrgLst[i].valid;
            var invalid = mrgLst[i].invalid;
      
            for (var j = 0; j < arr.length; j++) 
            {
              var test0 = arr[j].label
              if (test0 == valid) 
              {
                var subObj = {};
      
                subObj["label"] = valid
                subObj["visits"] = arr[j].visits
      
                for (var k = 0; k < arr.length; k++)
                {              
                  var test1 = arr[k].label
                  for (x in invalid)
                  {
                    if (test1 == invalid[x])
                    {
                      subObj["label"] = valid
                      subObj["visits"] += arr[k].visits
                    }
                  }
                }
              }
            }
            if (subObj != undefined)
            {
              obj.push(subObj)
            }
      
          }
      
          for (var i = 0; i < arr.length; i++) 
          {
            var original = arr[i]
            var org = {}
            var dont = false
      
            for (var j = 0; j < mrgLst.length; j++)
            {
              var test0 = mrgLst[j].valid
              var test1 = mrgLst[j].invalid
      
              if (original.label == test0)
              {
                dont = true
              }
              for (x in test1) 
              {
                if (original.label == test1[x])
                {
                  dont = true
                }
              }
            }
      
            if (dont == false)
            {
              org["label"] = original.label
              org["visits"] = arr[i].visits
      
              obj.push(org)
            }
          }
          return obj
        }
      

      作为任何有类似问题的人的参考。不再与 d3 有太大关系,但输出与 d3 一起使用...

      【讨论】:

        猜你喜欢
        • 2014-11-20
        • 1970-01-01
        • 1970-01-01
        • 2018-02-22
        • 2014-05-19
        • 1970-01-01
        • 2020-05-06
        • 1970-01-01
        • 2018-06-25
        相关资源
        最近更新 更多