如何过滤对象中特定键对应的值?

时间:2022-03-09 21:15:08

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):

类别是RM,CM,CO等。我写了一个函数,它将过滤掉类别(答案是一个更大的对象,值是其中的一部分):

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.

但现在我不确定如何获得与这些类别相对应的值。所以对于RM,我想要一个类似的数组:['很少','经常','有时','坚持''。同样适用于其他类别。

Any ideas? I feel like this is really quite simple and I'm missing something obvious.

有任何想法吗?我觉得这很简单,我错过了一些明显的东西。

6 个解决方案

#1


2  

You can simply use map on the array of categories to get their values in an array like this:

您可以简单地使用类别数组上的map来获取它们在数组中的值,如下所示:

const RM = getCategoryList("RM").map((key) => answers.values[key]);

#2


1  

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):

您可以根据属性名称的非数字部分动态生成类别,然后在一个reduce调用中将它们添加到最初为空的对象。这样,类别不是硬编码的(但需要符合相同的命名模式):

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));

#3


0  

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

您正在使用错误的变量valuesNames,使其成为您之前使用相同方法初始化的valueNames

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

此外,就像“RM1”.includes(“RM”)是真的,“ARM1”.includes(“RM”)也是如此

Use indexOf

  const getCategoryList = category => valueNames.filter(value => { 
    return value.indexOf(category) == 0;
  })

#4


0  

You could check with String#startsWith and use a Set for uniuque values

您可以使用String#startsWith进行检查,并使用Set来表示uniuque值

const getCategoryList = category =>
        [...new Set(valuesNames.filter(v => v.startsWith(category))];

#5


0  

Use for..in to iterate the object & indexOf to check if the key name has the passed string

使用for..in迭代对象&indexOf以检查键名是否具有传递的字符串

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'))

#6


0  

Here's a much compact solution using ES5.

这是一个使用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)

#1


2  

You can simply use map on the array of categories to get their values in an array like this:

您可以简单地使用类别数组上的map来获取它们在数组中的值,如下所示:

const RM = getCategoryList("RM").map((key) => answers.values[key]);

#2


1  

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):

您可以根据属性名称的非数字部分动态生成类别,然后在一个reduce调用中将它们添加到最初为空的对象。这样,类别不是硬编码的(但需要符合相同的命名模式):

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));

#3


0  

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

您正在使用错误的变量valuesNames,使其成为您之前使用相同方法初始化的valueNames

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

此外,就像“RM1”.includes(“RM”)是真的,“ARM1”.includes(“RM”)也是如此

Use indexOf

  const getCategoryList = category => valueNames.filter(value => { 
    return value.indexOf(category) == 0;
  })

#4


0  

You could check with String#startsWith and use a Set for uniuque values

您可以使用String#startsWith进行检查,并使用Set来表示uniuque值

const getCategoryList = category =>
        [...new Set(valuesNames.filter(v => v.startsWith(category))];

#5


0  

Use for..in to iterate the object & indexOf to check if the key name has the passed string

使用for..in迭代对象&indexOf以检查键名是否具有传递的字符串

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'))

#6


0  

Here's a much compact solution using ES5.

这是一个使用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)