如何在rxJS中展平或合并数组

时间:2017-12-21 15:07:45

标签: angular rxjs observable angular2-observables rxjs-lettable-operators

我有一个结构,我想扁平成一个同类数组。源数组如下所示:

[
  {
    "countryCode": "CA",
    "countryName": "Canada",
    "states": [
      {
        "stateCode": "CAAB",
        "stateName": "Alberta",
        "countryCode": "CA",
        "stateAbbrev": "AB"
      },
      . . . 
      {
        "stateCode": "CAYT",
        "stateName": "Yukon Territory",
        "countryCode": "CA",
        "stateAbbrev": "YT"
      }
    ]
  },
  {
    "countryCode": "US",
    "countryName": "USA",
    "states": [
      {
        "stateCode": "USAK",
        "stateName": "Alaska",
        "countryCode": "US",
        "stateAbbrev": "AK"
      },
      . . .
      {
        "stateCode": "USWY",
        "stateName": "Wyoming",
        "countryCode": "US",
        "stateAbbrev": "WY"
      }
    ]
  }
]

我想将其转换成这样的内容应该是这样的:

[
  {
    "value": "CA",
    "label": "Canada"
  },
  {
    "value": "CACB",
    "label": "Alberta"
  },
  . . .
  {
    "value": "CAYT",
    "label": "Yukon Territory"
  },
  {
    "value": "US",
    "label": "USA"
  },
  {
    "value": "USAK",
    "label": "Alaska"
  },
  . . .
  {
    "value": "USWY",
    "label": "Wyoming"
  }
]

到目前为止,我有:

let countries:Observable<ICountry[]> = 
   this.http.get<ICountry[]>(`${this.buildProUrl}/states`);

return countries.map(o => o.map(c => 
  <IStateDropDownItem>{value: c.countryCode, label: c.countryName}));

似乎应该有一种方法将属于每个国家/地区的状态合并到生成的可观察数组中。我已经阅读了concatMap,mergeMap和switchMap文档,但我无法弄清楚如何将它们放在一起。

1 个答案:

答案 0 :(得分:2)

我认为您只需要处理结果数组,可以使用Arry.reduce()函数来完成:

&#13;
&#13;
const data = [
  {
    "countryCode": "CA",
    "countryName": "Canada",
    "states": [
      {
        "stateCode": "CAAB",
        "stateName": "Alberta",
        "countryCode": "CA",
        "stateAbbrev": "AB"
      },
      {
        "stateCode": "CAYT",
        "stateName": "Yukon Territory",
        "countryCode": "CA",
        "stateAbbrev": "YT"
      }
    ]
  },
  {
    "countryCode": "US",
    "countryName": "USA",
    "states": [
      {
        "stateCode": "USAK",
        "stateName": "Alaska",
        "countryCode": "US",
        "stateAbbrev": "AK"
      },
      {
        "stateCode": "USWY",
        "stateName": "Wyoming",
        "countryCode": "US",
        "stateAbbrev": "WY"
      }
    ]
  }
];

console.log(data.reduce((res, curr) => {
  res.push({value: curr.countryCode, label: curr.countryName});
  return res.concat(curr.states.reduce((res, curr) => {
    res.push({value: curr.stateCode, label: curr.stateName});
    return res;
  }, [])); 
}, []));
&#13;
&#13;
&#13;

如果您使用新的httpClient,那么您的响应已经是一个数组,所以在您的情况下它应该有效:

let countries:Observable<ICountry[]> = 
  this.http.get<ICountry[]>(`${this.buildProUrl}/states`);

return countries.map(o => o.reduce((res, curr) => {
  res.push(<IStateDropDownItem>{value: curr.countryCode, label: curr.countryName});
  return res.concat(curr.states.reduce((res, curr) => {
    res.push(<IStateDropDownItem>{value: curr.stateCode, label: curr.stateName});
    return res;
  }, [])); 
}, []));