Although a plethora of posts have been dedicated to the topic, I still couldn't find a satisfying idea how to subset object properties of any depth. More so, I would also like to rename the selected keys on the fly.
What I'm aiming to achieve is a generic function, let's call it select(), that accepts two inputs:
- an object of data
- an object in which keys represent the desired new name, and values specify the path to desired properties.
For example, consider the following data:
const earthData = {
  distanceFromSun: 149280000,
  continents: {
    asia: {
      area: 44579000,
      population: 4560667108,
      countries: { japan: { temperature: 62.5 } },
    },
    africa: { area: 30370000, population: 1275920972 },
    europe: { area: 10180000, population: 746419440 },
    america: { area: 42549000, population: 964920000 },
    australia: { area: 7690000, population: 25925600 },
    antarctica: { area: 14200000, population: 5000 },
  },
};
My goal is to call select() this way:
const earthDataSubset = select(earthData, {
  distanceFromSun: ['distanceFromSun'],
  asiaPop: ['continents', 'asia', 'population'],
  americaArea: ['continents', 'america', 'area'],
  japanTemp: ['continents', 'asia', 'countries', 'japan', 'temperature'],
});
where the resulted earthDataSubset is
// earthDataSubset
{
    distanceFromSun: 149280000,
    asiaPop: 4560667108,
    americaArea: 42549000,
    japanTemp: 62.5
}
At this point, one may ask why I don't simply do this:
const earthDataSubsetSimple = {
    distanceFromSun: earthData.distanceFromSun,
    asiaPop: earthData.continents.asia.population,
    americaArea: earthData.continents.america.area,
    japanTemp: earthData.continents.asia.countries.japan.temperature
}
This won't work because typically, my data arrives as an array of objects, so I need to map over the array and apply the same select procedure such as in:
const earthData = {
    distanceFromSun: 149280000,
    continents: {
      asia: {
        area: 44579000,
        population: 4560667108,
        countries: { japan: { temperature: 62.5 } },
      },
      africa: { area: 30370000, population: 1275920972 },
      europe: { area: 10180000, population: 746419440 },
      america: { area: 42549000, population: 964920000 },
      australia: { area: 7690000, population: 25925600 },
      antarctica: { area: 14200000, population: 5000 },
    },
  };
  const earthData2050 = {
    distanceFromSun: 149280000,
    continents: {
      asia: {
        area: 44579000,
        population: 4560767108,
        countries: { japan: { temperature: 73.6 } },
      },
      africa: { area: 30370000, population: 1275960972 },
      europe: { area: 10180000, population: 746419540 },
      america: { area: 42549000, population: 964910000 },
      australia: { area: 7690000, population: 25928600 },
      antarctica: { area: 14200000, population: 5013 },
    },
  };
const myEarthArr = [earthData, earthData2050]
Admittedly, I could have called .map() array method simply as:
const mapRes = myEarthArr.map((record) => ({
  distanceFromSun: record.distanceFromSun,
  asiaPop: record.continents.asia.population,
  americaArea: record.continents.america.area,
  japanTemp: record.continents.asia.countries.japan.temperature,
}));
And get the desired output:
// [ { distanceFromSun: 149280000,
//     asiaPop: 4560667108,
//     americaArea: 42549000,
//     japanTemp: 62.5 },
//   { distanceFromSun: 149280000,
//     asiaPop: 4560767108,
//     americaArea: 42549000,
//     japanTemp: 73.6 } ]
Nevertheless, I'm looking to create my own generic select() function that accepts one object, and subsets it. The benefit of such approach is its flexibility. I can use it standalone on a single object, plus allowing me to scale select() to an array of objects when needed, by doing something like:
// pseudo code
myEarthArr.map( (record) => select(record, {
  distanceFromSun: ['distanceFromSun'],
  asiaPop: ['continents', 'asia', 'population'],
  americaArea: ['continents', 'america', 'area'],
  japanTemp: ['continents', 'asia', 'countries', 'japan', 'temperature'],
}) )
From looking around in StackOverflow posts, I found this one to be the closest. But neither do I understand how to shape it to my needs, nor whether its recursive mechanism actually required in my situation. By contrast, this post offers a ton of solutions for the simple scenario of subsetting, but none is addressing the issue of nested properties.
 
     
    