假设我有一个对象数组foo
,每个对象都有一个属性bar
,它是一个数组。
foo[0].bar = [1]
foo[1].bar = [2]
foo[2].bar = [2,4,5]
foo[3].bar = [2,4,6]
foo[4].bar = [2,4,6,7]
foo[5].bar = [2,4,6,9]
foo[6].bar = [3]
我需要一种方法来测试阵列并像这样进行特定的“最佳匹配”搜索:
mySearch([2,4,6]); // returns [foo[3], foo[4], foo[5]]
mySearch([2,4,6,7]); // returns [foo[4]]
mySearch([2,4,6,8]); // returns [foo[3]]
mySearch([3,2,1]); // returns [foo[6]]
mySearch([4]); // returns []
本质上,我希望foo[]
中的对象与测试数组中的尽可能多的精确数字匹配。顺序很重要,但是测试数组或目标对象的长度都是可变的。
我也许可以使用少量的for-next循环和if-thens来解决这个问题,但是我觉得应该有一个更好的方法。 (如果有帮助,我可以提供一个常量maxLength
,它等于集合中最长数组的长度。)
谢谢!
编辑:对不起,我在期望结果中的变量与上次编辑时有些混淆。
编辑2:对不起,我在描述这一点时非常困难。我正在处理的情况类似于阅读:给定标准英语词典中的字符串"HELLOWORL"
,我想要一个能找到适合的最长单词的函数:"HELLO"
(跳过{{1 }}和"HE"
也在字典中)。
答案 0 :(得分:1)
这是尝试,虽然不确定这是您追求的。
const foo = [{bar: [1]}, {bar: [2]}, {bar: [2,4,5]}, {bar: [2,4,6]}, {bar: [2,4,6,7]}, {bar: [2,4,6,9]}, {bar: [3]}];
function search(arr, minLengthMatch){
if (!minLengthMatch) // specify min match or use the default the arr length
minLengthMatch = arr.length;
return foo.filter(function(x){
var matchFound = 0;
for(var i in arr){
if (x.bar.indexOf(arr[i]) == i)
matchFound++;
else break; // tha match seq have been broken
}
return matchFound>=minLengthMatch
});
// change from .map to flatMap if you want a single array
}
console.log(search([2,4,6]));
答案 1 :(得分:1)
您可以使用foo
将JSON.stringify
数组的相同长度切片与输入数组进行比较(假设数组值很简单,就像示例中的整数一样)。然后,您需要根据何时匹配精确长度,更长和更短长度数组的规则,对foo
的适当子集进行迭代。
请参见下面的代码段
const matchBars = (objs, arr) => {
let matches = objs.reduce((acc, obj) => {
let len = arr.length <= obj.bar.length ? arr.length : obj.bar.length;
let a = JSON.stringify(arr.slice(0, len));
let b = JSON.stringify(obj.bar.slice(0, len));
if (a === b) {
if (len < arr.length) {
acc.short.push(obj);
} else {
acc.long.push(obj);
}
}
return acc;
}, {long: [], short: []});
if (!matches.long.length) {
return matches.short.sort((a, b) => b.bar.length - a.bar.length).slice(0, 1);
}
return matches.long;
}
const foo = [{bar: [1]}, {bar: [2]}, {bar: [2,4,5]}, {bar: [2,4,6]}, {bar: [2,4,6,7]}, {bar: [2,4,6,9]}, {bar: [3]}];
console.log(matchBars(foo, [2, 4, 6]));
// [{bar: [2,4,6]}, {bar: [2,4,6,7]}, {bar: [2,4,6,9]}]
console.log(matchBars(foo, [2, 4, 6, 8]));
// [{bar: [2,4,6]}]
答案 2 :(得分:1)
我不认为有一种非常简单的方法可以做到这一点,但就我所知,这将达到目的
const foo = [{bar: [1]}, {bar: [2]}, {bar: [2,4,5]}, {bar: [2,4,6]}, {bar: [2,4,6,7]}, {bar: [2,4,6,9]}, {bar: [3]}, {bar: [3, 4]}];
const mySearch = searchArray => {
var maxMatch = 0;
const searchString = searchArray.join("")
const matchingObjectsArray = foo.map(obj => {
const barString = obj.bar.join("")
if (barString.startsWith(searchString)
|| searchString.startsWith(barString)){
maxMatch = searchString.length >= barString.length ?
barString.length :
searchString.length
return obj
}else return null //if there are no matches replace obj with null
}).filter(Boolean) // get rid of nulls
const filteredMatches = matchingObjectsArray
.filter(obj => obj.bar.length >= maxMatch)
return filteredMatches
}
console.log(mySearch([3,4,6,9])) /* { bar: [ 3, 4 ] } ] */
答案 3 :(得分:1)
注意::该答案的较早版本在Javascript中滥用了foreach。此答案已被修改以解决此问题
我想我现在就知道了。
这是一个只有2个循环和2个ifs的解决方案:
注意::此解决方案假定foo是全局变量。传递foo或将
mySearch()
改为foo的成员函数可能是一个好主意,但希望这足以为您提供图片。
mySearch(test) {
var result[]; // the list of matches
var maxLen = 0; // to be filled later
// loop control vars.
var j=0;
var i=0;
// loop 1, for searching every bar
for(j=0;j<foo.length;j++) {
// if 1, for knowing our max length.
// Could be replaced with a ?:, but I don't remember if those exist in js
// if they do, it'd look something like
// maxLen = foo[j].bar.length > test.length ? test.length : foo[j].bar.length;
if(foo[j].bar.length > test.length) {
maxLen = test.length;
} else {
maxLen = foo[j].bar.length;
}
// a flag to hold if our current bar matches
var doesMatch = true;
// loop 2. This one is because we have a variable amount of
for(i =0; i<maxLen;i++) {
doesMatch = doesMatch && (foo[j].bar[i] == test[i]);
}
// if 2, see what we matched
if(doesMatch) {
// if we did, add it to the results
result.push(foo[j]);
}
}
// return what matched
return result;
}
希望这对于您正在寻找的东西足够有效。
P.S。使用?:语法,您可以将行maxLen = myFoo.bar.length > test.length ? test.length : foo[j].bar.length;
更改为 var
maxLen = foo[j].bar.length > test.length ? test.length : foo[j].bar.length;
,因为maxLen仅在循环中使用。
P.P.S。您还提到您已经有一个maxLength
可用,因此如果它的用途与我的maxLen
相同,那么您可以使用它。