我将如何更好地编写此reportCandidates的函数?

时间:2018-11-22 05:40:51

标签: javascript arrays json sorting collections

这是名为名为候选人数组的数组中的输入数据:

[ 
 {"name":"george","languages":["php","javascript","java"],"age":19,"graduate_date":1044064800000,"phone":"32-991-511"},
 {"name":"anna","languages":["java","javascript"],"age":23,"graduate_date":1391220000000,"phone":"32-991-512"},
 {"name":"hailee","languages":["regex","javascript","perl","go","java"],"age":31,"graduate_date":1296525600000,"phone":"32-991-513"}
]

由于该功能,我需要在这个集合中进行变换:

{candidates: [
    {name: "George", age: 19, phone: "32-991-511"},
    {name: "Hailee", age: 31, phone: "32-991-513"},
    {name: "Anna", age: 23, phone: "32-991-512"}
],
languages: [
    {lang:"javascript",count:1}, 
    {lang:"java", count:2}, 
    {lang:"php", count:2}, 
    {lang:"regex", count:1}
]}

函数repCandidates:

  

const reportCandidates = (candidatesArray) => { return repObject}

  • 我需要用javascript ES6编写
  • 我不应该使用循环(for,while,repeat),但是允许foreach,如果我使用“ reduce”功能可能会更好
  • 应按毕业生的姓名,年龄和电话归还候选人。
  • 应按字母顺序返回语言及其计数器。

请访问https://codepen.io/rillervincci/pen/NEyMoV?editors=0010以查看我的代码。

3 个答案:

答案 0 :(得分:1)

一个选择是首先reduce进入candidates子对象,而push将每个langauges放入数组。

迭代之后,对candidates进行排序,并从每个候选项中删除graduate_date属性,然后再次使用reducelanguages数组转换为按语言索引的一个,递增每次count属性:

const input = [{
  "name": "george",
  "languages": ["php", "javascript", "java"],
  "age": 19,
  "graduate_date": 1044064800000,
  "phone": "32-991-511"
}, {
  "name": "anna",
  "languages": ["java", "javascript"],
  "age": 23,
  "graduate_date": 1391220000000,
  "phone": "32-991-512"
}, {
  "name": "hailee",
  "languages": ["regex", "javascript", "perl", "go", "java"],
  "age": 31,
  "graduate_date": 1296525600000,
  "phone": "32-991-513"
}];


const output = input.reduce((a, { languages, ...rest }) => {
  a.candidates.push(rest);
  a.languages.push(...languages);
  return a;
}, { candidates: [], languages: [] });

output.candidates.sort((a, b) => a.graduate_date - b.graduate_date);
output.candidates.forEach(candidate => delete candidate.graduate_date);

output.languages = Object.values(
  output.languages.reduce((a, lang) => {
    if (!a[lang]) a[lang] = { lang, count: 0 };
    a[lang].count++;
    return a;
  }, {})
);
output.languages.sort((a, b) => a.lang.localeCompare(b.lang));

console.log(output);

答案 1 :(得分:0)

您可以像下面一样使用Array.reduceObject.values

let arr = [{"name":"george","languages":["php","javascript","java"],"age":19,"graduate_date":1044064800000,"phone":"32-991-511"},{"name":"anna","languages":["java","javascript"],"age":23,"graduate_date":1391220000000,"phone":"32-991-512"},{"name":"hailee","languages":["regex","javascript","perl","go","java"],"age":31,"graduate_date":1296525600000,"phone":"32-991-513"}]


let res = arr.reduce((o, {name, age, phone, graduate_date, languages}) => {
    o.candidates.push({name, age, phone, graduate_date})
  
    languages.forEach(l => {
      o.languages[l] = o.languages[l] || { lang:l, count: 0 }
      o.languages[l].count++
    })
  
    return o
  }
 , { candidates: [], languages: {}})

res.candidates = res.candidates.sort((a,b) => a.graduate_date - b.graduate_date)
                               .map(({ graduate_date, ...rest }) => rest)

res.languages = Object.values(res.languages).sort((a,b) => a.lang.localeCompare(b.lang))
  
console.log(res)

答案 2 :(得分:0)

reduce()中进行所有操作是一种常见的做法,但是如果您将其分解一点,有时会更容易阅读。这将创建一个counter对象作为跟踪语言计数的助手。 map()遍历数组以提取语言和个人信息,然后将它们放在一起:

let arr = [ {"name":"george","languages":["php","javascript","java"],"age":19,"graduate_date":1044064800000,"phone":"32-991-511"},{"name":"anna","languages":["java","javascript"],"age":23,"graduate_date":1391220000000,"phone":"32-991-512"},{"name":"hailee","languages":["regex","javascript","perl","go","java"],"age":31,"graduate_date":1296525600000,"phone":"32-991-513"}]
 
let lang_counter = {
  // helper keeps counts of unique items
  counts:{},
  add(arr){
     arr.forEach(item => this.counts[item] = this.counts[item] ? this.counts[item] + 1 : 1)
  },
  toarray(){
    return Object.entries(this.counts).map(([key, val]) => ({[key]: val}))
  }
}

// iterate over object to create candidates 
let candidates = arr.map(row => {
  let {languages, ...person} = row
  lang_counter.add(languages)  // side effect
  return person
})

// put them together
console.log({candidates, languages:lang_counter.toarray()})