0

I am trying to turn a array that exists of objects with a nested array inside it into a new array that consist of the values inside the nested array separately(Might sound very complicated but example show very clear)

What I have:

const values = [{
    geometry: {
      "coordinates": [11.4828, 59.1264],
      "Type": "point"
    },
    properties: {
      Region: "Oklahoma",
      sales: {
        donuts: {
          2005: 5,
          2006: 8,
          2007: 10
        },
        apples: {
          2005: 10,
          2006: 8,
          2007: 10
        }
      }
    }
  },
  {
    geometry: {
      "coordinates": [9.4828, 76.1264],
      "Type": "point"
    },
    properties: {
      Region: "Texas",
      sales: {
        donuts: {
          2005: 8,
          2006: 0,
          2007: 7
        },
        apples: {
          2005: 7,
          2006: 9,
          2007: 4
        }
      }
    }
  }
]
const filterValue = "donuts"

What My goal is:

newValues =[{geometry: {"coordinates": [11.4828, 59.1264],"Type":"point"},properties:{Region: "Oklahoma",value:5,time:2005}},{geometry: {"coordinates": [11.4828, 59.1264],"Type":"point"},properties:{Region: "Oklahoma",value:8,time:2006}},{geometry: {"coordinates": [11.4828, 59.1264],"Type":"point"},properties:{Region: "Oklahoma",value:10,time:2007}} AND SO ON FOR ALL THE values that are in const donuts/filter for each value. Could also switch out value for donuts if that is easier
}
]

What I have tried so far:

const newObject = []
values.map((value)=>{
  console.log(value.properties.sales.donuts)
  for (var key in value.properties.sales.donuts) {
        if (value.properties.sales.donuts.hasOwnProperty(key)) {
            newObject.push({...value,value.properties:{[key]:value.properties.sales.donuts[key]})
        }
    }
})
console.log(newObject)

2 Answers 2

2

Your current syntax is invalid - value.properties: { is not a valid key in an object literal. Since you want the output properties property to contain data corresponding to the region and year too, you should include those in the object being pushed. Since you also don't need the year to be a key in the new object, but a value (with a value property), the object being pushed should reflect that.

You should only use .map when you're returning a value inside the mapper function to create a new array. If you're iterating only to perform side-effects, you should use a more appropriate generic iteration method, like for..of or forEach. In this case, since you want to create multiple objects in the output array from one associated object in the input array, .flatMap would be more appropriate.

Map the .donuts entries and return the new object with geometry and properties properties.

const values=[{geometry:{coordinates:[11.4828,59.1264],Type:"point"},properties:{Region:"Oklahoma",sales:{donuts:{2005:5,2006:8,2007:10},apples:{2005:10,2006:8,2007:10}}}},{geometry:{coordinates:[9.4828,76.1264],Type:"point"},properties:{Region:"Texas",sales:{donuts:{2005:8,2006:0,2007:7},apples:{2005:7,2006:9,2007:4}}}}];

const filterValue = "donuts";
const output = values.flatMap(({ geometry, properties }) =>
    Object.entries(properties.sales[filterValue]).map(([year, saleCount]) => ({
        geometry,
        properties: {
            Region: properties.Region,
            value: saleCount,
            time: year,
        }
    }))
);
console.log(output);

Sign up to request clarification or add additional context in comments.

3 Comments

can properties.sales.donuts be changed to properties.sales[filterValue] instead for a dynamic option?
What are those comments? /**ref:3**/, is it possible to avoid them?
@matieva That's just an artifact of the Stack Snippet's console. Look at the results in the browser console instead - the output structure is as desired.
1

You'll need a flatmap here

const values = [
  {
    geometry: {
      coordinates: [11.4828, 59.1264],
      Type: 'point',
    },
    properties: {
      Region: 'Oklahoma',
      sales: {
        donuts: {
          2005: 5,
          2006: 8,
          2007: 10,
        },
        apples: {
          2005: 10,
          2006: 8,
          2007: 10,
        },
      },
    },
  },
  {
    geometry: {
      coordinates: [9.4828, 76.1264],
      Type: 'point',
    },
    properties: {
      Region: 'Texas',
      sales: {
        donuts: {
          2005: 8,
          2006: 0,
          2007: 7,
        },
        apples: {
          2005: 7,
          2006: 9,
          2007: 4,
        },
      },
    },
  },
];
const mapData = (data, filterBy) => {
  return data.flatMap((state) => {
    return Object.entries(state.properties.sales[filterBy]).map(
      ([time, value]) => {
        return {
          ...state,
          properties: {
            region: state.properties.Region,
            time,
            value,
          },
        };
      }
    );
  });
};

const mappedDonuts = mapData(values, 'donuts');
console.log(mappedDonuts);

2 Comments

I would not like it like that. I would like to have each year in a different Object. So it ends up like something this: docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson
ah, I see! I have updated the code according to your desired data format.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.