Reputation: 771
I need to separate out the values in an object by category, which is visible from the key names of the object. Here is part of what the object may look like:
const values = {
RM1: 'Rarely',
RM2: 'Often',
RM3: 'Sometimes',
RM4: 'Consistently',
CM1: 'Rarely',
CM2: 'Never',
CM3: 'Sometimes',
CM4: 'Sometimes',
CO1: 'Often',
CO2: 'Often',
CO3: 'Often',
CO4: 'Sometimes'
}
The categories are RM, CM, CO, etc. I wrote a function that will filter out the categories (answers
is a larger object that values
is a part of):
const categorizeAnswers = (answers) =>{
const valueNames = Object.keys(answers.values);
const values = Object.values(answers.values);
const getCategoryList = category => valueNames.filter(value => {
return value.includes(category);
})
const RM = getCategoryList("RM");
const CM = getCategoryList("CM");
const CO = getCategoryList("CO");
}
But now I'm not sure how to get the values that correspond to those categories. So for RM
, I want an array like: ['Rarely', 'Often', 'Sometimes', 'Consistently']
. And likewise for the other categories.
Any ideas? I feel like this is really quite simple and I'm missing something obvious.
Upvotes: 1
Views: 68
Reputation: 147363
You could generate the categories dynamically based on the non–digit part of the property name, then add them to an initially empty object all in one reduce call. That way the categories aren't hard coded (but need to fit the same naming pattern):
var values = {
RM1: 'Rarely',
RM2: 'Often',
RM3: 'Sometimes',
RM4: 'Consistently',
CM1: 'Rarely',
CM2: 'Never',
CM3: 'Sometimes',
CM4: 'Sometimes',
CO1: 'Often',
CO2: 'Often',
CO3: 'Often',
CO4: 'Sometimes'
}
function getCategories(data) {
return Object.keys(data).reduce(function(acc, key){
var p = key.replace(/\d+/,'');
acc[p]? acc[p].push(data[key]) : acc[p] = [data[key]];
return acc;
}, Object.create(null));
}
console.log(getCategories(values));
Upvotes: 1
Reputation: 420
You can simply use map on the array of categories to get their values in an array like this:
const RM = getCategoryList("RM").map((key) => answers.values[key]);
Upvotes: 2
Reputation: 827
Here's a much compact solution using ES5.
const getCategoryList = (category) => {
const categories = [].concat(Object.keys(answers.values).filter((value) => value.includes(category)));
const values = [].concat(categories.map((value) => answers.values[value]));
return [categories, values]
}
const [ categories, values ] = getCategoryList('RM');
console.log(categories, values)
Upvotes: 0
Reputation: 50291
Use for..in
to iterate the object & indexOf
to check if the key name has the passed string
var values = {
RM1: 'Rarely',
RM2: 'Often',
RM3: 'Sometimes',
RM4: 'Consistently',
CM1: 'Rarely',
CM2: 'Never',
CM3: 'Sometimes',
CM4: 'Sometimes',
CO1: 'Often',
CO2: 'Often',
CO3: 'Often',
CO4: 'Sometimes'
}
function getValues(keyName) {
var valArray = [];
for (let keys in values) {
if (keys.indexOf(keyName) !== -1 && valArray.indexOf(values[keys]) === -1) {
valArray.push(values[keys])
}
}
return valArray;
}
console.log(getValues('CO'))
Upvotes: 0
Reputation: 386540
You could check with String#startsWith
and use a Set
for uniuque values
const getCategoryList = category =>
[...new Set(valuesNames.filter(v => v.startsWith(category))];
Upvotes: 0
Reputation: 68383
Any ideas? I feel like this is really quite simple and I'm missing something obvious.
You are using a wrong variable valuesNames
, make it valueNames
which you had initialized in the same method before
var categorizeAnswers = (answers) =>{
const valueNames = Object.keys(answers.values);
const values = Object.values(answers.values);
const getCategoryList = category => valueNames.filter(value => { //notice the change from valuesNames to valueNames
return value.includes(category);
})
const RM = getCategoryList("RM");
console.log(RM);
const CM = getCategoryList("CM");
const CO = getCategoryList("CO");
}
Also, Just like "RM1".includes("RM")
is true
, "ARM1".includes("RM")
is also true
Use indexOf
const getCategoryList = category => valueNames.filter(value => {
return value.indexOf(category) == 0;
})
Upvotes: 0