比较两个对象数组并在新数组中返回匹配值
Posted
技术标签:
【中文标题】比较两个对象数组并在新数组中返回匹配值【英文标题】:Compare two array of objects and return matching values in a new array 【发布时间】:2022-01-02 19:23:22 【问题描述】:我有两个对象数组:inputData
和 jobList
。我必须比较两个对象数组的 primarySkills 数组,并仅返回两个数组中匹配的值。我的对象数组如下:
let inputData = [
"candidateID": "911772331",
"skillSet": ["Information Technology"],
"addressCity": "Bengaluru",
"addressState": "KA",
"country": "India",
"primarySkills": ['asp.net', 'react', 'javascript'],
"secondarySkills": ['powerbi', 'redux'],
"preferredPositionType": [],
]
let jobList = [
jobId: '600039355',
jobType: 'fulltime',
primarySkills: [ 'asp.net','node' ],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'Indonesia, Bekasi Kabupaten, 53, Jalan Londan 5',
City: 'Bekasi Kabupaten',
State: 'JABODETABEK',
Zipcode: '17522',
Country: 'Indonesia'
,
jobId: '562190375',
jobType: 'fulltime',
primarySkills: [ 'javascript','mainframe' ],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'India, Pune, 411001, Pune, Pune Station',
City: 'Pune',
State: 'MH',
Zipcode: '411001',
Country: 'India'
,
jobId: '883826845',
jobType: 'fulltime',
primarySkills: [ 'sqlserver', 'react', 'powershell' ],
secondarySkills: [ 'powerbi' ],
skillSet: [ 'powerbi' ],
Address: 'ประเทศไทย, หมู่ที่ 3, 1234',
City: 'หมู่ที่ 3',
State: null,
Zipcode: '57110',
Country: 'ประเทศไทย'
]
我已经完成了下面提到的代码来实现这一点:
jobList.forEach((item) =>
inputData.forEach((data) =>
for (let i = 0; i <= item.primarySkills.length; i++)
for (let j = 0; j <= data.primarySkills.length; j++)
if (item.primarySkills[i] === data.primarySkills[j])
PMSkill.push(item.primarySkills[i]);
else
PMSkill.push(0)
)
)
Expected output to be like in the PMSkill array:
let PMSkill= [
jobId: '600039355',
jobType: 'fulltime',
primarySkills: [ 'asp.net'],----here asp.net is the only skill matching with inputData primarySkill
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'Indonesia, Bekasi Kabupaten, 53, Jalan Londan 5',
City: 'Bekasi Kabupaten',
State: 'JABODETABEK',
Zipcode: '17522',
Country: 'Indonesia'
,
jobId: '562190375',
jobType: 'fulltime',
primarySkills: [ 'javascript'],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'India, Pune, 411001, Pune, Pune Station',
City: 'Pune',
State: 'MH',
Zipcode: '411001',
Country: 'India'
,
jobId: '883826845',
jobType: 'fulltime',
primarySkills: ['react'],
secondarySkills: [ 'powerbi' ],
skillSet: [ 'powerbi' ],
Address: 'ประเทศไทย, หมู่ที่ 3, 1234',
City: 'หมู่ที่ 3',
State: null,
Zipcode: '57110',
Country: 'ประเทศไทย'
]
【问题讨论】:
问题是什么?你的代码不起作用吗?如果是这样 - 会发生什么以及应该发生什么?如果代码不起作用,那么您需要什么帮助? 是的,代码不起作用。目前发生的情况是 PMSkill 数组给出了错误或空白值。预期的是两个对象数组的primarySkills 字段应该是comapred 并且应该返回PMSkill 数组中的共同值。 @tanu ... OP 通常还描述了预期的结果/输出。 对不起,这是我第一次@这个平台,所以错过了。当 inputData 第一次与 JobList 进行比较时,预期的输出应该是 ['javascript']。打印两个对象数组中的共同值。 【参考方案1】:您好,有一个我经常使用的简单方法
function arr_intersection(a1: number[], a2: number[])
return a1.filter((x) => a2.includes(x));
你也可以使用lodash中的交集方法
const _ = require("lodash");
// Original array
let array1 = [1, 2, 4, 3, 4, 4]
let array2 = [2, 4, 5, 6]
let array3 = [2, 3, 5, 6]
// Using _.intersection() method
let newArray = _.intersection(
array1, array2, array3);
// Printing original Array
console.log("original Array1: ", array1)
console.log("original Array2: ", array2)
console.log("original Array3: ", array3)
// Printing the newArray
console.log("new Array: ", newArray)
这里你可以发送多个数组,不像我的方法
【讨论】:
【参考方案2】:function getIntersection(x, y)
// ensure two arrays ...
const [
comparisonBase, // ... the shorter one as comparison base
comparisonList, // ... the longer one to filter from.
] = [[...x], [...y]]
.sort((a, b) => a.length - b.length);
// create a `Map` based lookup table from the shorter array.
const itemLookup = comparisonBase
.reduce((map, item) => map.set(item, true), new Map)
// the intersection is the result of following filter task.
return comparisonList.filter(item => itemLookup.has(item));
const inputData = [
"candidateID": "911772331",
"skillSet": ["Information Technology"],
"addressCity": "Bengaluru",
"addressState": "KA",
"country": "India",
"primarySkills": ['asp.net', 'react', 'javascript'],
"secondarySkills": ['powerbi', 'redux'],
"preferredPositionType": [],
];
const jobList = [
jobId: '600039355',
jobType: 'fulltime',
primarySkills: [ 'javascript' ],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'Indonesia, Bekasi Kabupaten, 53, Jalan Londan 5',
City: 'Bekasi Kabupaten',
State: 'JABODETABEK',
Zipcode: '17522',
Country: 'Indonesia'
,
jobId: '562190375',
jobType: 'fulltime',
primarySkills: [ 'javascript' ],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'India, Pune, 411001, Pune, Pune Station',
City: 'Pune',
State: 'MH',
Zipcode: '411001',
Country: 'India'
,
jobId: '883826845',
jobType: 'fulltime',
primarySkills: [ 'sqlserver', 'azure', 'powershell' ],
secondarySkills: [ 'powerbi' ],
skillSet: [ 'powerbi' ],
Address: 'ประเทศไทย, หมู่ที่ 3, 1234',
City: 'หมู่ที่ 3',
State: null,
Zipcode: '57110',
Country: 'ประเทศไทย'
];
const candidateSkills = inputData[0].primarySkills;
const openJobsSkills = [...new Set(
jobList.reduce((arr, primarySkills ) => arr.concat(primarySkills), [])
)];
const skillIntersection = getIntersection(openJobsSkills, candidateSkills);
console.log( candidateSkills, openJobsSkills, skillIntersection );
.as-console-wrapper min-height: 100%!important; top: 0;
编辑根据 OP 的更详细的进一步要求
“我想将
inputData.primarySkills
与jobList
中的每个对象列表一一进行比较,并针对jobList
的primarySkills
字段更新匹配技巧。” p>
在这种情况下,需要一项任务,该任务将 jobList
的 forEach
项目重新分配为 primarySkills
属性值,并与从 inputData
获取的基本 primarySkills
数组的属性特定交集。
所提供的解决方案利用forEach
及其2nd thisArg
argument 将功能与外部范围引用/依赖项分离。
根据是否需要让 jobList
保持不变/未触及,on 可能需要额外的映射任务,该任务必须创建每个 jobList
项目的深层克隆。
function getIntersection(x, y)
// ensure two arrays ...
const [
comparisonBase, // ... the shorter one as comparison base
comparisonList, // ... the longer one to filter from.
] = [[...x], [...y]]
.sort((a, b) => a.length - b.length);
// create a `Map` based lookup table from the shorter array.
const itemLookup = comparisonBase
.reduce((map, item) => map.set(item, true), new Map)
// the intersection is the result of following filter task.
return comparisonList.filter(item => itemLookup.has(item));
const inputData = [
"candidateID": "911772331",
"skillSet": ["Information Technology"],
"addressCity": "Bengaluru",
"addressState": "KA",
"country": "India",
"primarySkills": ['asp.net', 'react', 'javascript'],
"secondarySkills": ['powerbi', 'redux'],
"preferredPositionType": [],
];
const jobList = [
jobId: '600039355',
jobType: 'fulltime',
primarySkills: [ 'asp.net','node' ],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'Indonesia, Bekasi Kabupaten, 53, Jalan Londan 5',
City: 'Bekasi Kabupaten',
State: 'JABODETABEK',
Zipcode: '17522',
Country: 'Indonesia'
,
jobId: '562190375',
jobType: 'fulltime',
primarySkills: [ 'javascript','mainframe' ],
secondarySkills: [ 'javascript' ],
skillSet: [ 'javascript' ],
Address: 'India, Pune, 411001, Pune, Pune Station',
City: 'Pune',
State: 'MH',
Zipcode: '411001',
Country: 'India'
,
jobId: '883826845',
jobType: 'fulltime',
primarySkills: [ 'sqlserver', 'react', 'powershell' ],
secondarySkills: [ 'powerbi' ],
skillSet: [ 'powerbi' ],
Address: 'ประเทศไทย, หมู่ที่ 3, 1234',
City: 'หมู่ที่ 3',
State: null,
Zipcode: '57110',
Country: 'ประเทศไทย'
];
function updatePrimarySkillsWithIntersectionOfBoundBaseSkills(jobItem)
const basePrimarySkills = this;
jobItem.primarySkills =
getIntersection(jobItem.primarySkills, basePrimarySkills);
// if needed ... create new array with real `jobItem` clones ...
const pmSkillList = jobList.map(jobItem =>
JSON.parse(JSON.stringify(jobItem))
);
// ... otherwise (`jobList.forEach`) ... just ...
// .... reassign the item specific `primarySkills` property value.
pmSkillList.forEach(
// the callback
updatePrimarySkillsWithIntersectionOfBoundBaseSkills,
// the 2nd `thisArg` argument
inputData[0].primarySkills,
);
// log any involved data.
console.log( inputData, jobList, pmSkillList );
.as-console-wrapper min-height: 100%!important; top: 0;
【讨论】:
感谢@Peter Seliger 回答我的问题。您能否再帮我一个方案(我还在我的代码 sn-p 中更新了上面的预期输出)。我想将 inputdata[primarySkills] 与 jobList 中的每个对象列表一一进行比较,并根据 jobList 的 primarySkills 字段更新匹配技能。 你能帮我@Peter Seliger 上面解释的场景吗 @tanu ... 完成。 非常感谢@Peter Seliger。再次回答我的问题真的很有帮助,非常好心。再次感谢!!!【参考方案3】:像这样更改您的验证
matchingPrimarySkills = []
jobList.forEach((job) =>
inputData.forEach((candidate) =>
job.primarySkills.forEach( (jobPrimarySkill) =>
candidate.primarySkills.forEach( (candidatePrimarySkill) =>
if (jobPrimarySkill === candidatePrimarySkill && matchingPrimarySkills.indexOf(jobPrimarySkill) === -1)
matchingPrimarySkills.push(jobPrimarySkill)
)
)
)
)
// With your examples, it will og [ "javascript"] without duplicates
console.log(matchingPrimarySkills)
【讨论】:
【参考方案4】:这是实现所需输出的一种方法。仅显示相关属性仅用于演示。您可以将候选人从inputData
传递给getJobs(input)
函数,以从输入中获取与primarySkills
匹配的职位列表:
let inputData = [
candidateID: '111111', primarySkills: ['asp.net', 'react', 'javascript'] ,
candidateID: '222222', primarySkills: ['python'] ,
candidateID: '333333', primarySkills: ['powershell', 'node'] ,
]
let jobList = [
jobId: '77777', primarySkills: ['asp.net', 'node'] ,
jobId: '88888', primarySkills: ['javascript', 'python'] ,
jobId: '99999', primarySkills: ['sqlserver', 'azure', 'powershell'] ,
]
function getJobs(input)
// Get a copy of jopList
const temp = jobList.map(obj => return ...obj )
return temp.filter(job =>
// Filter the job's primarySkills to only show
// skills matching the candidates's primarySkills.
job.primarySkills = job.primarySkills.filter(jobSkill =>
input.primarySkills.includes(jobSkill)
)
return job.primarySkills.length
)
// Get jobs for all candidates in inputData
for (let candidate of inputData)
console.log(`\nJobs for candidateID $candidate.candidateID:\n`, getJobs(candidate))
【讨论】:
以上是关于比较两个对象数组并在新数组中返回匹配值的主要内容,如果未能解决你的问题,请参考以下文章