如何根据搜索关键字对字符串数组进行排序?

时间:2020-12-01 07:08:24

I've an array of strings. I need to sort the array based on array of keywords. The string containing max. number of keywords should come first and so on. Also, the string which contains max. no. of search keywords should come first than the number of occurrences of same search keyword. testArray should ignore case of searchTerms. If possible, you can ignore the strings which doesn't contain any search keywords in the result array.

我有一系列字符串。我需要根据关键字数组对数组进行排序。包含最大值的字符串首先应该有关键字的数量,依此类推。另外,包含最大值的字符串。没有。搜索关键字的首先应该是相同搜索关键字的出现次数。 testArray应该忽略searchTerms的情况。如果可能,您可以忽略结果数组中不包含任何搜索关键字的字符串。

var testArray = [
    "I am",
    "I am wrong and I don't know",
    "I am right and I know",
    "I don't know",
    "I do know"
  ],
  searchTerms = ["I", "right","know"];

$.each(searchTerms, function(index, term) {
  var regX = new RegExp(term, "i");
  testArray = $.map(testArray, function(item) {
    if (regX.test(item)) {
      return item;
    } else {
      return;
    }
  });
});

console.log(testArray);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

If you observe in the above code, the keywords are "I", "right","know". So the testArray results should be as below,

如果您在上面的代码中观察到,关键字是“我”,“正确”,“知道”。所以testArray的结果如下,

testArray = [
    "I am right and I know",    
    "I am wrong and I don't know",    
    "I don't know",
    "I do know",
    "I am"
  ]

string contain all the keywords come first and the other strings contain "I","know", So they come next and string "I am" comes last as it contains only "I" keyword.

string首先包含所有关键字,其他字符串包含“I”,“know”,所以它们接下来,字符串“I am”排在最后,因为它只包含“I”关键字。

Codepen

3 个解决方案

#1


1  

You can try something like this:

你可以尝试这样的事情:

Idea:

  • Loop over data and criteria and create a Map that has both count and value.
  • 循环遍历数据和条件,并创建具有计数和值的Map。

  • Use a regex to match the string. This way you can do case-insensitive search.
  • 使用正则表达式匹配字符串。这样您就可以进行不区分大小写的搜索。

  • Sort this Map based on count.
  • 根据计数对此地图进行排序。

  • Return list of values.
  • 返回值列表。

function getMatchCountMap(data, criterias) {
  return data.reduce((countMap, curItem) => {
    var count = criterias.filter((criteria) => new RegExp(criteria, 'i').test(curItem) ).length;
    countMap.push({
      value: curItem,
      count: count
    });
    return countMap;
  }, [])
}

function sortBasedOnCount(data, criterias) {
  var map = getMatchCountMap(data, criterias);
  map.sort((a, b) => b.count - a.count);
  return map.map(x => x.value);
}

var testArray = [
    "I am",
    "I am wrong and I don't know",
    "I am right and I know",
    "I don't know",
    "I do know"
  ],
  searchTerms = ["I", "right","know"];
  
console.log(sortBasedOnCount(testArray, searchTerms))

#2


1  

You could try to create regex with those terms and sort by the number of matches, something like:

您可以尝试使用这些术语创建正则表达式并按匹配数排序,例如:

var testArray = [
    "I am",
    "i,i,i will come first i'm RIGHT i do KNOW",
    "I am wrong and I don't know",
    "I am right and I know",
    "I don't know",
    "I do know",
    "Something else"
  ],

  searchTerms = ["I", "right", "know"];


// (?:I)|(?:right)|(?:know)
const searchExp = new RegExp(searchTerms.reduce((acc, term) => acc ? `${acc}|(?:${term})` : `(?:${term})`, ''), 'gi');

const result = testArray.sort((a, b) => {
  const bMatch = b.match(searchExp) || [];
  const aMatch = a.match(searchExp) || [];

  return bMatch.length - aMatch.length;
});

console.log(result);

#3


1  

You could take an object for the counting and sort by the count of the string.

您可以使用一个对象进行计数,并按字符串的计数进行排序。

var array = [ "I am", "I am wrong and I don't know", "i am RIGHT and I know", "I don't know", "I do know", "i,i,i will come first i'm RIGHT i do KNOW"],
    search = ["I", "am","know"].map(v => v.toLowerCase()),
    count = array.reduce((c, k) => {
        var a = k.toLowerCase().split(/[^a-z0-9']+/),
            count = Object.create(null);

        a.forEach(w => count[w] = (count[w] || 0) + 1);
        c[k] = [0, 0];
        search.forEach(v => {
            c[k][0] += v in count;
            c[k][1] += count[v] || 0;
        });
        return c;
    }, Object.create(null));
  
array.sort((a, b) => count[b][0] - count[a][0] || count[b][1] - count[a][1]);

console.log(array);

#1


1  

You can try something like this:

你可以尝试这样的事情:

Idea:

  • Loop over data and criteria and create a Map that has both count and value.
  • 循环遍历数据和条件,并创建具有计数和值的Map。

  • Use a regex to match the string. This way you can do case-insensitive search.
  • 使用正则表达式匹配字符串。这样您就可以进行不区分大小写的搜索。

  • Sort this Map based on count.
  • 根据计数对此地图进行排序。

  • Return list of values.
  • 返回值列表。

function getMatchCountMap(data, criterias) {
  return data.reduce((countMap, curItem) => {
    var count = criterias.filter((criteria) => new RegExp(criteria, 'i').test(curItem) ).length;
    countMap.push({
      value: curItem,
      count: count
    });
    return countMap;
  }, [])
}

function sortBasedOnCount(data, criterias) {
  var map = getMatchCountMap(data, criterias);
  map.sort((a, b) => b.count - a.count);
  return map.map(x => x.value);
}

var testArray = [
    "I am",
    "I am wrong and I don't know",
    "I am right and I know",
    "I don't know",
    "I do know"
  ],
  searchTerms = ["I", "right","know"];
  
console.log(sortBasedOnCount(testArray, searchTerms))

#2


1  

You could try to create regex with those terms and sort by the number of matches, something like:

您可以尝试使用这些术语创建正则表达式并按匹配数排序,例如:

var testArray = [
    "I am",
    "i,i,i will come first i'm RIGHT i do KNOW",
    "I am wrong and I don't know",
    "I am right and I know",
    "I don't know",
    "I do know",
    "Something else"
  ],

  searchTerms = ["I", "right", "know"];


// (?:I)|(?:right)|(?:know)
const searchExp = new RegExp(searchTerms.reduce((acc, term) => acc ? `${acc}|(?:${term})` : `(?:${term})`, ''), 'gi');

const result = testArray.sort((a, b) => {
  const bMatch = b.match(searchExp) || [];
  const aMatch = a.match(searchExp) || [];

  return bMatch.length - aMatch.length;
});

console.log(result);

#3


1  

You could take an object for the counting and sort by the count of the string.

您可以使用一个对象进行计数,并按字符串的计数进行排序。

var array = [ "I am", "I am wrong and I don't know", "i am RIGHT and I know", "I don't know", "I do know", "i,i,i will come first i'm RIGHT i do KNOW"],
    search = ["I", "am","know"].map(v => v.toLowerCase()),
    count = array.reduce((c, k) => {
        var a = k.toLowerCase().split(/[^a-z0-9']+/),
            count = Object.create(null);

        a.forEach(w => count[w] = (count[w] || 0) + 1);
        c[k] = [0, 0];
        search.forEach(v => {
            c[k][0] += v in count;
            c[k][1] += count[v] || 0;
        });
        return c;
    }, Object.create(null));
  
array.sort((a, b) => count[b][0] - count[a][0] || count[b][1] - count[a][1]);

console.log(array);