Javascript 将对象数组转换为结构

Javascript 将对象数组转换为结构,javascript,arrays,node.js,object,Javascript,Arrays,Node.js,Object,目前,我正在使用一个api,它返回一个对象数组 [{match_id: "255232", country_id: "41", country_name: "England", league_id: "152", league_name: "National League", match_date: "2020-01-01", match_status: "", match_time: "16:00"}, {match_id: "255232", country_id: "41",

目前,我正在使用一个api,它返回一个对象数组

[{match_id: "255232",
country_id: "41",
country_name: "England",
league_id: "152",
league_name: "National League",
match_date: "2020-01-01",
match_status: "",
match_time: "16:00"},
{match_id: "255232",
    country_id: "41",
    country_name: "Italy",
    league_id: "152",
    league_name: "Serie a",
    match_date: "2020-01-01",
    match_status: "",
    match_time: "16:00"},
{match_id: "255232",
        country_id: "41",
        country_name: "Italy",
        league_id: "153",
        league_name: "Serie b",
        match_date: "2020-01-01",
        match_status: "",
        match_time: "16:00"},...
    ...

]
我想以一种最终看起来像:

const transformed = [
{
    country_name: "England",
    entries: [
        {league_name: "National League",
        events: [{},{}]}
    ]

},
{country_name: "Italy",
entries: [
    {
        league_name: "Serie a",
        events: [{},{}]
    },
    {
        league_name: "Serie b",
        events: [{},{}]
    }...
]]
我曾尝试使用.reduce,但最终没有得到预期的输出,结果只是得到了一个还原的结构。基本上我需要的是先按国家名称分类,然后按联赛名称分类


显然,数据是动态的,国家/联盟的名称经常变化。

我提供了两种解决方案-一种是返回由国家和联盟名称键入的对象(这是我的首选/建议),另一种是扩展第一种解决方案以返回您请求的形状

第一段代码将您的输入转换为一个由国家和联盟名称键入的对象:

const data=[{match\u id:“255232”,country\u id:“41”,country\u name:“英格兰”,league\u id:“152”,league\u name:“国家联盟”,match\u date:“2020-01-01”,match\u status:“16:00”,match\u id:“255233”,country\u id:“41”,country\u name:“意大利”,league\u id:“152”,league\u name:“意甲”,match\u date:“2020-01-01”,match\u status:“match\u time:“16:00”},{比赛id:“255234”、国家id:“41”、国家名称:“意大利”、联赛id:“152”、联赛名称:“意甲”、比赛日期:“2020-01-01”、比赛状态:“16:00”}]
const transformed=data.reduce(
(acc,{国家队名,联赛名,…比赛})=>{
acc[国家名称]=acc[国家名称]| |{}
acc[国家名称][联盟名称]=acc[国家名称][联盟名称][联盟名称]
acc[国家/地区名称][联盟名称].推送(比赛)
返回acc
},
{}
)

console.log(transformed)
我提供了两种解决方案—一种是返回由国家和联盟名称键入的对象(这是我的首选/建议),另一种是扩展第一种解决方案以返回您请求的形状

第一段代码将您的输入转换为一个由国家和联盟名称键入的对象:

const data=[{match\u id:“255232”,country\u id:“41”,country\u name:“英格兰”,league\u id:“152”,league\u name:“国家联盟”,match\u date:“2020-01-01”,match\u status:“16:00”,match\u id:“255233”,country\u id:“41”,country\u name:“意大利”,league\u id:“152”,league\u name:“意甲”,match\u date:“2020-01-01”,match\u status:“match\u time:”16:00“},{比赛id:“255234”,国家id:“41”,国家名称:“意大利”,联赛id:“152”,联赛名称:“意甲”,比赛日期:“2020-01-01”,比赛状态:“,比赛时间:”16:00}]
const transformed=data.reduce(
(acc,{国家队名,联赛名,…比赛})=>{
acc[国家名称]=acc[国家名称]| |{}
acc[国家名称][联盟名称]=acc[国家名称][联盟名称][联盟名称]
acc[国家/地区名称][联盟名称].推送(比赛)
返回acc
},
{}
)

log(转换)
这似乎是
for
循环的一个用例,它创建或
推送每个“结果”“输入相应的国家指数,然后使用类似的逻辑按联赛组织每个国家的比赛。下面的代码非常详细——如果您使用Lodash之类的实用程序库,您可以通过
groupBy
之类的工具更简洁地实现其中的一些功能(尽管这样会生成一个对象而不是数组)

const results=[/*…您的原始数据…*/];
const resultsByCountry=[];
//第一个循环只是按国家对匹配项进行索引:
for(设r=0;rcountry.country\u name==result.country\u name);
//暂时,我们只是把比赛放在这里。一旦我们知道他们都被分到了正确的国家,我们会再传一次,把他们分到联赛中:
如果(现有国家索引>-1){
resultsByCountry[existingCountryIndex].entries.push(结果);
}否则{
结果按国家/地区({
国家/地区名称:result.country\u名称,
参赛作品:[结果]
});
}
}
//第二个循环通过非常类似的方式将比赛组织成联盟:
for(设c=0;cleague.league\u name==match.league\u name);
如果(现有联盟索引>-1){
matchesByLeague[existingLeagueIndex]。事件。推送(比赛);
}否则{
matchesByLeague.push({
联赛名称:match.league\u name,
事件:[匹配]
});
}
}
//使用分组数组覆盖旧的'entries'键:
country.entries=matchesByLeague;
}
console.log(结果按国家/地区);
同样,这是相当粗糙的。可能有一种方法可以通过
map
reduce
来实现它,但是由于数据结构不寻常,并且特别提出了从数组转换为数组(而不是对象)的问题,因此我将此作为一个简单而明确的答案


这似乎是
for
循环的一个用例,它创建或
将每个“结果”推送到相应的国家索引中,然后使用类似的逻辑按联赛组织每个国家的比赛。下面的代码非常详细——如果您使用Lodash之类的实用程序库,您可以通过
groupBy
之类的工具更简洁地实现其中的一些功能(尽管这样会生成一个对象而不是数组)

const results=[/*…您的原始数据…*/];
const resultsByCountry=[];
//第一个循环只是按国家对匹配项进行索引:
for(设r=0;rcountry.country\u name==result.country\u name);
//暂时,我们只是把比赛放在这里。一旦我们知道他们都被分到了r,我们会再传一次,把他们分到联赛中
const map1 = {};
const list = matches.map(match => {
  if (!map1[match.country_name]) {
    map1[match.country_name] = {};
  }
  map1[match.country_name]["entries"] =
    map1[match.country_name]["entries"] &&
    map1[match.country_name]["entries"].length > 0
      ? map1[match.country_name]["entries"].concat(match)
      : [match];
});

const result = [];
Object.keys(map1).forEach(country => {
  const m = {};
  m["country_name"] = country;
  m["entries"] = [];
  const entries = map1[country]["entries"];

  entries.forEach(entry => {
    m["entries"].push({
      league_name: entry.league_name,
      events: entry
    });
  });

  result.push(m);
});
// result has the required info.