首页 > 解决方案 > 如何将一个数组中的首字母与另一个数组中的值匹配?

问题描述

我有以下代码检查以确保数组 1 中的至少一个值出现在数组 2 中。

只要它存在,它就会检查array2中是否存在任何首字母(长度为一个字符的值)。

如果有,它将检查该初始值是否与 array1 中任何值的第一个字母匹配。

var array1 = ['Bob', 'Freddy', 'Johnson'];
var array2 = ['Bob', 'Johnson', 'F'];
var isValid = '';

if (array1.some(v => array2.includes(v)) == true) { //At least one value in array 1 appear in array 2
  if (anyInitials(array2) == 'yes') { // initials appear in array 2
    if (findName(array2, array1) == true) { //check initials in array 2 vs array 1
      isValid = 'yes';
    } else { //let's check the inverse, just in case
      isValid = 'no';
    }
  }
}
console.log('Do we match? = ' + isValid);

function findName(arr1, arr2) {
  for (let initial of arr1) {
    if (initial.length === 1) {
      return arr2.findIndex(name => name[0] === initial) != -1
    }
  }
}

function anyInitials(a) {
  var arrayLength = a.length;
  var isInitials = 'no';

  for (var i = 0; i < arrayLength; i++) {
    if (a[i].length == 1) {
      isInitials = 'yes';
    }
  }

  return isInitials;
}

一切正常,但我在更复杂的场景中遇到问题,例如:

var array1 = ['Bob','Freddy', 'Johnson', 'Frank'];
var array2 = ['Bob', 'Johnson', 'Frank', 'F'];

如何确保 array2 中的初始“F”正在针对 array1 中的“Freddy”而不是“Frank”进行测试(因为 Frank 存在于两个数组中,应该忽略它)?

还,

var array1 = ['Bob','Freddy', 'Johnson', 'Frank', 'Frederic'];
var array2 = ['Bob', 'Johnson', 'F', 'F'];

在上面,第一个“F”应该针对“Freddy”进行测试,第二个“F”应该针对“Frank”进行测试,因为 Freddy 已经匹配。但是,我们在“Frederic”中有一个余数,它没有对应的匹配项(array2 中没有剩下的名称)所以 isValid 应该说“不”;

更复杂的情况:

var array1 = ['Bob','F', 'Freddy', 'Johnson', 'Frank'];
var array2 = ['Bob', 'J', 'F', 'Johnson', 'Freddy'];

"J" 不应该找到匹配项,因为 "Johnson" 已经有一对。一个“F”应该自动匹配它的对,而第二个“F”应该测试剩下的“Frank”。这让 "Frank" 与 "J" 进行测试,它应该返回 "no"。

此时数组 1 中的哪个名称与数组 2 对中的初始名称无关。重要的是它是否可以配对。

任何一个数组都可以包含尽可能多的值或尽可能少的值(每个值至少为 1)。

谢谢

附录:到目前为止,提议的解决方案将涉及从两个数组中删除所有匹配的名称,只留下每个不同的值。这仍然给我留下了将首字母与名称匹配的问题(修改后的 findName 函数)。然后需要从两个数组中删除这些这样的对,只留下每个数组中的余数(如果有的话)。如果 array1 中有余数,则 isValid 会说“不”。

标签: javascriptarrays

解决方案


你不能真正一步完成,你将不得不分两步完成。

  • 第一步是过滤所有一对一匹配的内容。
  • 之后,您必须确定您是否有姓名首字母或全名并进行匹配。

var names1 = ['Bob','Freddy', 'Johnson', 'Frank', 'Frederic'];
var names2 = ['Bob', 'Johnson', 'F', 'F', 'F'];
var names3 = ['Bob', 'Johnson', 'F', 'F', 'G'];
var names4 = ['Bob', 'Johnson', 'F', 'F'];

function test (array1, array2) {

  // If lenghts differ, then it fails
  if (array1.length !== array2.length) {
    return false
  }

  // copy arrays so you do not alter orginals
  var first = array1.slice()
  var second = array2.slice()

  // remove the exact matches
  array1.forEach( function (name, index) {
    var secondIndex = second.indexOf(name)
    if (secondIndex > -1) {
      first.splice(first.indexOf(name), 1)
      second.splice(secondIndex, 1)
    }
  })

  // if all matched, then we pass
  if (!first.length) {
    return true;
  }

  // now check to see if we have a abv match, 
  // every item in the array needs a match to pass
  return first.every(function (text) {
    var index = -1
    // if we have a full name, than match first
    if (text.length > 1) {
      var index = second.indexOf(text[0])
    } else {
      // we have an initial so need to first letter in full name
      var index = second.findIndex( function (secondText) {
        return text === secondText[0]
      })
    }
    // if we do not have a match then we have a failure
    if (index === -1) {
      return false
    } else {
      // when we have a match, remove it from the second so it can not be used again
      second.splice(index, 1)
      return true
    }
  })
}

console.log(1, test(names1, names1))
console.log(2, test(names1, names2))
console.log(3, test(names2, names1))
console.log(4, test(names1, names3))
console.log(5, test(names3, names1))
console.log(6, test(names1, names4))


推荐阅读