如何仅使用给定字符匹配一个单词一次

How to match a word using a given character only once

我试图找到一个正则表达式模式来匹配一个单词和一些给定的字符。但是每个字符只能使用一次。例如,如果我得到“yrarbil”(库向后),它应该匹配这些:

但应该不符合以下

我四处搜索,但我能找到的最好的是匹配单词的代码,但同一字符的使用次数超过了给出的次数。谢谢。

P.S:如果这不能在正则表达式中完成(如你所见,我是一个菜鸟)以编程方式匹配这样的单词的最佳方法是什么?

我不明白你为什么要在有非常简单直接的解决方案的情况下使用正则表达式来执行此操作。

您只需计算每个字母在给定单词和您测试的单词中出现的次数。然后检查测试单词中的每个字母出现的次数是否不超过给定单词中的出现次数。

for ch in given_word
    cnt[ch]++
for ch in test_word
    cnt[ch]--
for ch='a'..'z'
    if cnt[ch]<0
        answer is no
if for all leters cnt[ch]>=0 
    answer is yes

正则表达式对此不起作用。一种解决方案是简单地计算列表中的字符数。

例如 JavaScript:

function count(str){
  return str.split('').reduce(function(m,c){
     m[c] = (m[c]||0)+1;
     return m;
  },{})
}
function check(str, reference){
   var ms = count(str), mr = count(reference);
   for (var k in ms) {
     if (!(ms[k]<=mr[k])) return false;
   }
   return true;
}

// what follows is only for demonstration in a snippet
$('button').click(function(){
  $('#r').text(check($('#a').val(), "library") ? "OK":"NOT OK");
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id=a value="rarlib">
<button>CHECK</button>
<div id=r></div>

"library" 令人困惑,因为它有 2 窝 r。但在我看来是可以解决的。

轻松创建一个 map<char, int> 这将存储模式中每个字符的计数。然后我们将为要检查的单词生成一个 map<char, int>,它还将包含每个字符的计数,然后如果任何字符的计数多于它不匹配的模式映射中的相同字符,则遍历映射,如果根本找不到,那么它也不匹配。

根据需要使用 C# 中的代码 使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Text; 使用 System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static bool Match(string pattern, string toMatch)
        {
            Dictionary<char, int> patternMap = new Dictionary<char, int>();
            Dictionary<char, int> toMatchMap = new Dictionary<char, int>();

            foreach (char ch in pattern)
            {
                if (patternMap.ContainsKey(ch))
                    ++patternMap[ch];
                else
                    patternMap[ch] = 1;
            }
            foreach (char ch in toMatch)
            {
                if (toMatchMap.ContainsKey(ch))
                    ++toMatchMap[ch];
                else
                    toMatchMap[ch] = 1;
            }

            foreach (var item in toMatchMap)
            {
                if (!patternMap.ContainsKey(item.Key) || patternMap[item.Key] < item.Value)
                    return false;
            }
            return true;
        }
        static void Main(string[] args)
        {
            string pattern = "library";
            string[] test = { "lib", "rarlib", "rarrlib", "ll" };
            foreach (var item in test)
            {
                if(Match(pattern, item))
                    Console.WriteLine("Match item : {0}", item);
                else
                    Console.WriteLine("Failed item : {0}", item);
            }
            Console.ReadKey();

            /*
Match item : lib
Match item : rarlib
Failed item : rarrlib
Failed item : ll

             */
        }
    }
}