这是名为candidatesArray的数组中的输入数据:
[
{"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}
请访问 https://codepen.io/rillervincci/pen/NEyMoV?editors=0010 查看我的代码。
一种选择是首先将
reduce
放入 candidates
子对象中,同时 push
将每个 langauges
放入数组中。
迭代后,对
candidates
进行排序并从每个候选者中删除 graduate_date
属性,然后再次使用 reduce
将 languages
数组转换为按语言索引的数组,每次递增 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);
通常的做法是在
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()})
您可以使用
Array.reduce
和 Object.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)
如果您愿意使用不仅仅是普通 JavaScript,我可以提供直观的解决方案。
import assert from "assert";
import { ORDER } from "@ut8pia/classifier/global.js";
import { TrueSet } from "@ut8pia/classifier/queue/TrueSet.js";
const
data = [
{"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"}
],
expected = {
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: "go", count: 1},
{lang: "java", count: 3},
{lang: "javascript", count: 3},
{lang: "perl", count: 1},
{lang: "php", count: 1},
{lang: "regex", count: 1}
]};
要定义
report(data)
函数,您只需要 representation
函数和 TrueSets
。候选人以毕业日期代表,而语言则以自我代表。 TrueSet
一致地统计了每个项目的出现频率。只需将您的数据添加到 TrueSets
即可。
function report(data) {
const
candidates = TrueSet.of(candidate => candidate.graduate_date, ORDER.ASCENDING, ORDER.INSERTION)
.letAll(data),
languages = new TrueSet(language => language)
.letAll(data
.map(candidate => candidate.languages)
.flat());
return {
candidates:
candidates
.toArray()
.map(candidate => ({name: candidate.name, age: candidate.age, phone: candidate.phone})),
languages:
languages
.toArray()
.map(language => ({lang: language, count: languages.n(language)}))
}
}
您可以通过以下方式验证结果:
const got = report(data);
assert.deepEqual(got, expected);