处理对象数组中的某些属性

Process certain properties in array of objects

我正在尝试处理对象数组中的一些属性。

顺序总是一样的,因为在第二个 属性 之后总是接下来的 12 个条目的日期范围,之后的所有内容都被排除在外,有时可以是两个,就像在这个例子中或者可能更多。

所以我想做的是排除除关键字和日期范围之外的所有内容。

const data = [{
  "keyword": "foo",
  // This key never changes
  "search_vol": 0,
  // These keys can change when they start, i.e. starts jan-21
  "jul-20": 10,
  "aug-20": 10,
  "sep-20": 10,
  "oct-20": 10,
  "nov-20": 10,
  "dec-20": 10,
  "jan-21": 10,
  "feb-21": 10,
  "mar-21": 10,
  "apr-21": 20,
  "may-21": 10,
  "jun-21": 10,
  // These would change to different properties in name and amount
  "drain": "FALSE",
  "toilet": "TRUE"
}, {
  "keyword": "faa",

  "search_vol": 100,

  "jul-20": 880,
  "aug-20": 880,
  "sep-20": 880,
  "oct-20": 880,
  "nov-20": 880,
  "dec-20": 880,
  "jan-21": 1000,
  "feb-21": 880,
  "mar-21": 1000,
  "apr-21": 720,
  "may-21": 880,
  "jun-21": 880,

  "drain": "TRUE",
  "toilet": "TRUE"
}]

我想这样做,以便稍后我可以获得每个对象日期的最大值,并有一个条目包含达到该最大值的月份

预期最终输出:

const data = [{
  "keyword": "foo",
  "search_vol": 0,
  "jul-20": 10,
  "aug-20": 10,
  "sep-20": 10,
  "oct-20": 10,
  "nov-20": 10,
  "dec-20": 10,
  "jan-21": 10,
  "feb-21": 10,
  "mar-21": 10,
  "apr-21": 20,
  "may-21": 10,
  "jun-21": 10,
  "Max months": ['apr-21'],
  "drain": "FALSE",
  "toilet": "TRUE"
}, {
  "keyword": "faa",
  "search_vol": 100,
  "jul-20": 880,
  "aug-20": 880,
  "sep-20": 880,
  "oct-20": 880,
  "nov-20": 880,
  "dec-20": 880,
  "jan-21": 1000,
  "feb-21": 880,
  "mar-21": 1000,
  "apr-21": 720,
  "may-21": 880,
  "jun-21": 880,
  "Max months": ['jan-21','mar-21'],
  "drain": "TRUE",
  "toilet": "TRUE"
}]

是否值得将流程分开,先搁置日期,然后获取最大值,还是最好一次完成所有流程?

这是我的尝试,不包括与数据的合并,但我认为过于复杂

const data = [{
  "keyword": "foo",
  "search_vol": 0,

  "jul-20": 10,
  "aug-20": 10,
  "sep-20": 10,
  "oct-20": 10,
  "nov-20": 10,
  "dec-20": 10,
  "jan-21": 10,
  "feb-21": 10,
  "mar-21": 10,
  "apr-21": 20,
  "may-21": 10,
  "jun-21": 10,

  "drain": "FALSE",
  "toilet": "TRUE"
}, {
  "keyword": "faa",
  "search_vol": 100,

  "jul-20": 880,
  "aug-20": 880,
  "sep-20": 880,
  "oct-20": 880,
  "nov-20": 880,
  "dec-20": 880,
  "jan-21": 1000,
  "feb-21": 880,
  "mar-21": 1000,
  "apr-21": 720,
  "may-21": 880,
  "jun-21": 880,

  "drain": "TRUE",
  "toilet": "TRUE"
}]

const headers = Object.keys(data[0]).filter((_, index) => index === 0 || ( index >=  1 && index <= 13))

const dates = data.reduce((acc, obj) => {
  const filtered = headers.reduce((entries, key) => ({ ...entries, [key]: obj[key] }), {})
  acc.push(filtered)
  return acc
}, [])

const months = dates.map(({ keyword, ...dates }) => {
  const max = Math.max(...Object.values(dates))
  
  const maxMonths = Object.entries(dates).reduce((acc, [key, value]) => {
    if (value === max) acc.push(key)
    return acc
  }, [])


  return {
    keyword,
    'Max months': maxMonths,
  }
})

console.log(months)

这是适合您的解决方案

const data = [
  { 'keyword': 'foo', 'search_vol': 0, 'jul-20': 10, 'aug-20': 10, 'sep-20': 10, 'oct-20': 10, 'nov-20': 10, 'dec-20': 10, 'jan-21': 10, 'feb-21': 10, 'mar-21': 10, 'apr-21': 20, 'may-21': 10, 'jun-21': 10, 'drain': 'FALSE', 'toilet': 'TRUE' },
  { 'keyword': 'faa', 'search_vol': 100, 'jul-20': 880, 'aug-20': 880, 'sep-20': 880, 'oct-20': 880, 'nov-20': 880, 'dec-20': 880, 'jan-21': 1000, 'feb-21': 880, 'mar-21': 1000, 'apr-21': 720, 'may-21': 880, 'jun-21': 880, 'drain': 'TRUE', 'toilet': 'TRUE' }
];

const expected = data.map(_obj => {
  // convert object to an array and filter out the values that are not needed
  const filteredArr = Object.entries(_obj)
    .filter(entry => !['keyword', 'search_vol'].includes(entry[0]))
    .slice(0, 12);

  // find the max value in the array
  const max = Math.max(...filteredArr.map(entry => entry[1]));

  // find the list of months with max value
  const maxMonths = filteredArr.filter(entry => entry[1] === max).map(entry => entry[0]);

  return {
    ..._obj,
    'Max Months': maxMonths
  }
})

console.log(expected);

@abranhe 的回答很好,但我仍然担心依赖键的顺序。当您执行 Object.keys.

时,键将被排序

你可以替换这个:

  const filteredArr = Object.entries(_obj)
    .filter(entry => !['keyword', 'search_vol'].includes(entry[0]))
    .slice(0, 12);

有了这个:

  const filteredArr = Object.entries(_obj)
    .filter(entry => entry[0].match(/[a-z]{3}-[0-9]{2}/) !== null)

随着代码的不断变化,这会更加健壮:)