Oxnard
Oxnard

Reputation: 269

rxjs/angular how to convert http response to array-like object

need to convert a json response body into a array-like object in an Angular 13 environment

the incoming response data looks like:

 [
    {
      "n": 1,
      "s": "s1"
    },
    {
      "n": 2,
      "s": "s2"
    },
    {
      "n": 3,
      "s": "s3"
    }
  ]

the resulting array-like object needs to look like

{
   numArray: [1,2,3],
  stringArray: ['s1','s2','s3']
}

have tried using map, flatmap, toArray + others from RxJS library seem to be unable to make the list. generally end up with:

{n: 1, s: 's1'}
{n: 2, s: 's2'}
{n: 3, s: 's3'}

how to do this translation?

Upvotes: 0

Views: 269

Answers (1)

Adrian Brand
Adrian Brand

Reputation: 21658

A reduce is what you need, you need a starting accumulator that has the arrays for collecting strings and numbers and each iteration push the current items properties into the corresponding array on the accumulator

const result = [
  {
    "n": 1,
    "s": "s1"
  },
  {
    "n": 2,
    "s": "s2"
  },
  {
    "n": 3,
    "s": "s3"
  }
].reduce(
  (acc, current) => {
    acc.numArray.push(current.n);
    acc.stringArray.push(current.s);
    return acc;
  },
  { numArray: [], stringArray: [] } // your starting accumulator
);

console.log(result);

or you could use two maps but then you are iterating the array twice

const array = [
  {
    "n": 1,
    "s": "s1"
  },
  {
    "n": 2,
    "s": "s2"
  },
  {
    "n": 3,
    "s": "s3"
  }
];

const results = {
  numArray: array.map(item => item.n),
  stringArray: array.map(item => item.s)
};

console.log(results);

so in your Angular service you use the RxJs map operator and in the function you pass in you use the array's built in reduce or map function. When you have an RxJs stream and you want to transform the value emitted by the stream that is always a map, the function passed into the map then does the transformation and in this case of transforming an array we use the array's built in functions such as map, filter, find or reduce.

this.http('yourApiUrl').pipe(
  map(result => result.reduce(
    (acc, current) => {
      acc.numArray.push(current.n);
      acc.stringArray.push(current.s);
      return acc;
    },
    { numArray: [], stringArray: [] } // your starting accumulator
  ))
)

or

this.http('yourApiUrl').pipe(
  map(result => ({
    numArray: result.map(item => item.n),
    stringArray: result.map(item => item.s)
  }))
)

Upvotes: 1

Related Questions