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.