将对象转换为计数数组

Turning objects into an array of counts

本文关键字:数数 数组 对象 转换      更新时间:2023-09-26

我正试图把注意力集中在一个需要解决的问题上,但似乎没有取得任何进展。我想做的事情很可能更容易举例说明。

我有一个对象数组,看起来像这样:

[
  {"city_name": "New York", "visited": "2014-10-20"},
  {"city_name": "New York", "visited": "2014-10-20"},
  {"city_name": "New York", "visited": "2014-10-20"},
  {"city_name": "New York", "visited": "2014-10-21"},
  {"city_name": "New York", "visited": "2014-10-21"},
  {"city_name": "Stockholm", "visited": "2014-10-20"},
  {"city_name": "Stockholm", "visited": "2014-10-20"},
  {"city_name": "Stockholm", "visited": "2014-10-21"},
  {"city_name": "Stockholm", "visited": "2014-10-21"},
]

现在,我想实现的是将这个阵列变成以下阵列:

[
  {
    "key": "New York",
    "values": [
       ['2014-10-20', 3], // Because there were 3 visits in New York at this date
       ['2014-10-21', 2]  // Because there were 2 visits in New York at this date
    ]
  },
  {
    "key": "Stockholm",
    "values": [
       ['2014-10-20', 2],
       ['2014-10-21', 2]
    ]
  }
]

我尝试使用MapReduce函数(来自Underscore.js)来解决这个问题,但在未能生成我想要的输出后,以及其他几次尝试的相同(失败)结果,我决定在这里提问。也许有人知道该做什么?

而且,对这个可怕的标题感到抱歉。如果你对此有更好的想法,请评论(可能也会帮助其他人解决这个问题)

您可以创建一个中间数据结构来跟踪这两个国家和每个国家的访问情况;然后将该结构映射到最终输出中:

var tmp = {};
visits.forEach(function(item) {
  var obj = tmp[item.city_name] || (tmp[item.city_name] = {});
  obj[item.visited] = (obj[item.visited] || 0) + 1;
});
var result = Object.keys(tmp).map(function(key) {
  return {
    key: key,
    values: Object.keys(tmp[key]).map(function(date) {
      return [date, tmp[key][date]];
    })
  };
});

如果使用Undercore是一个选项:

var result = _.chain(arr).groupBy('city_name').map(function (el, key) {
    return {
        key: key,
        values: _.chain(el).countBy('visited').pairs().value()
    }
}).value();

到此为止:

function make_it_so(src)
{
    var usd={}, rsl=[], idx=-1;
    src.forEach(function(val,key,arr)
    {
        var cty = val["city_name"];
        if (!usd[cty])
        {
            idx++;
            usd[cty] = {};
            rsl[idx] = {"key":cty, "values":[]};
        }
        if (!usd[cty][val["visited"]])
        {
            usd[cty][val["visited"]] = val["visited"];
            rsl[idx]["values"][rsl[idx]["values"].length] = val["visited"];
        }
    });
    return rsl;
}
var src = [
    {"city_name": "New York", "visited": "2014-10-20"},
    {"city_name": "New York", "visited": "2014-10-20"},
    {"city_name": "New York", "visited": "2014-10-20"},
    {"city_name": "New York", "visited": "2014-10-21"},
    {"city_name": "New York", "visited": "2014-10-21"},
    {"city_name": "Stockholm", "visited": "2014-10-20"},
    {"city_name": "Stockholm", "visited": "2014-10-20"},
    {"city_name": "Stockholm", "visited": "2014-10-21"},
    {"city_name": "Stockholm", "visited": "2014-10-21"}
];
console.log(make_it_so(src));

我的解决方案使用"reduce"answers"map"来计算计数和转换数据:

function countVisitDates(visits) {
  // Count the visits per city per date using "reduce".
  var counts = visits.reduce(function(memo, visit) {
    var cityName=visit.city_name, visitDate=visit.visited;
    if (!memo[cityName]) { memo[cityName] = {}; }
    memo[cityName][visitDate] |= 0;
    memo[cityName][visitDate] += 1;
    return memo;
  }, {});
  // Transform the count structure using "map".
  return Object.keys(counts).map(function(cityName) {
    return {
      key: city_name,
      values: Object.keys(counts[cityName]).map(function(date) {
        return [date, counts[cityName][date]];
      })
    };
  });
};
countVisitDates(data);
/* =>
[
  {
    "key": "New York",
    "values": [
      [ "2014-10-20", 3 ],
      [ "2014-10-21", 2 ]
    ]
  },
  {
    "key": "Stockholm",
    "values": [
      [ "2014-10-20", 2 ],
      [ "2014-10-21", 2 ]
    ]
  }
]
*/

您只需遍历数据:

var data = [
  {"city_name": "New York", "visited": "2014-10-20"},
  {"city_name": "New York", "visited": "2014-10-20"},
  {"city_name": "New York", "visited": "2014-10-20"},
  {"city_name": "New York", "visited": "2014-10-21"},
  {"city_name": "New York", "visited": "2014-10-21"},
  {"city_name": "Stockholm", "visited": "2014-10-20"},
  {"city_name": "Stockholm", "visited": "2014-10-20"},
  {"city_name": "Stockholm", "visited": "2014-10-21"},
  {"city_name": "Stockholm", "visited": "2014-10-21"},
];
var newdata = {};
data.forEach(function(entry) {
  var city = entry.city_name;
  var time = entry.visited;
  if(!newdata[city]) {
    newdata[city] = {};
  }
  if(!newdata[city][time]) {
    newdata[city][time]=0;
  }
  newdata[city][time]++;
});

这给出了一个等价结构,然后可以根据需要使用Object.keys():进行转换

{
  "New York": {
    "2014-10-20": 3,
    "2014-10-21": 2
  }
  ,
  ...
}