比较两个对象数组并在新数组中返回匹配值

Posted

技术标签:

【中文标题】比较两个对象数组并在新数组中返回匹配值【英文标题】:Compare two array of objects and return matching values in a new array 【发布时间】:2022-01-02 19:23:22 【问题描述】:

我有两个对象数组:inputDatajobList。我必须比较两个对象数组的 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.primarySkillsjobList中的每个对象列表一一进行比较,并针对jobListprimarySkills字段更新匹配技巧。” p>

在这种情况下,需要一项任务,该任务将 jobListforEach 项目重新分配为 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))

【讨论】:

以上是关于比较两个对象数组并在新数组中返回匹配值的主要内容,如果未能解决你的问题,请参考以下文章

比较两个对象数组,并将匹配值的元素排除到JS中的新数组中

如何在 es6 中仅比较和过滤两个对象数组中不匹配的数组

Javascript:从包含对象的多维数组中返回不匹配的值

如何映射两个数组并将匹配项作为按钮返回?

如何映射两个数组并将匹配作为按钮返回?

javascript - 在对象数组中,返回任何值与特定字符串匹配的对象