Home > Software engineering >  How to map over an array of objects to extract values corresponding to keys that start with a prefix
How to map over an array of objects to extract values corresponding to keys that start with a prefix

Time:03-22

I have an array of objects that looks like that:

const myArr = [
  {id: 1,
  some_data: {
    "color_1": {
      "value": "red"
    },
    "color_2": {
      "value": "blue"
    },
    "color_3": {
      "value": "yellow"
    },
    "shape_1": {
      "value": "square"
    },
    "shape_2": {
      "value": "circle"
    }
  }
  },
  {id: 2,
     some_data: {
    "color_1": {
      "value": "pink"
    },
    "color_2": {
      "value": "orange"
    },
    "color_3": {
      "value": "yellow"
    },
    "shape_1": {
      "value": "square"
    },
    "shape_2": {
      "value": "triangle"
    }
  }
  },
  {id: 3,
  /* some_data: {...}*/},
  {id: 4,
  /* some_data: {...}*/}
]

I want to go over myArr and extract the values that correspond to colors, to end up with this array:

// desired output
["red", "blue", "yellow", "pink", "orange", "yellow"]

So I figured out that I would need to use String.prototype.startsWith() on the keys. Unfortunately, I have been unsuccessful in all my attempts to map over myArr.

Inspired by this answer I tried:

const oneAttempt = myArr.map((obj) =>
        Object.keys(obj.some_data)
            .filter((v) => v.startsWith('color'))
            .map((e) => obj.some_data[e].value)
    );

But it's not quite what I need. It's probably a pretty simple thing but I'm failing to figure this out.

CodePudding user response:

You need only the object of some_data and get a flat mapping.

const
    data = [{ id: 1, some_data: { color_1: { value: "red" }, color_2: { value: "blue" }, color_3: { value: "yellow" }, shape_1: { value: "square" }, shape_2: { value: "circle" } } }, { id: 2, some_data: { color_1: { value: "pink" }, color_2: { value: "orange" }, color_3: { value: "yellow" }, shape_1: { value: "square" }, shape_2: { value: "triangle" } } }],
    result = data.flatMap(({ some_data }) => Object
        .keys(some_data)
        .filter(k => k.startsWith('color_'))
        .map(k => some_data[k].value)
    );

console.log(result);

CodePudding user response:

You can use a combination of Array#map(), Array#filter() and Object#entries() as in the demo below:

const myArr = [{id: 1,some_data: {"color_1": {"value": "red"},"color_2": {"value": "blue"},"color_3": {"value": "yellow"},"shape_1": {"value": "square"},"shape_2": {"value": "circle"}}},{id: 2,some_data: {"color_1": {"value": "pink"},"color_2": {"value": "orange"},"color_3": {"value": "yellow"},"shape_1": {"value": "square"},"shape_2": {"value": "triangle"}}}];

// desired output
//["red", "blue", "yellow", "pink", "orange", "yellow"]

const desiredOutput = myArr.map(
    ({some_data}) => 
    Object.entries(some_data).filter(
        ([key,{value}]) =>
        key.startsWith('color_')
    )
    .map(([key,{value}]) => value)
)
.flat();
//OUTPUT:
//["red", "blue", "yellow", "pink", "orange", "yellow"]

console.log( desiredOutput );

  • Related