将json条目与d3合并

时间:2013-12-09 16:32:01

标签: javascript json d3.js

我正在进行一些可视化,需要合并某些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组合在一起。保留所有其他未合并的内容。

3 个答案:

答案 0 :(得分: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/

答案 1 :(得分:1)

我会研究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/

答案 2 :(得分:0)

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

它是这样的:

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 ...

一起使用