【问题标题】:Match existing characters together into words and check if the words appear in the given word list?将现有字符匹配成单词并检查单词是否出现在给定单词列表中?
【发布时间】:2021-10-23 00:03:25
【问题描述】:

我有一个这样的单词列表:

string[] listWords = "la,lam,lan,son,som,some,mos,mao,sehi,noesrh,nroeh,doise".Split(',');

上面列出的单词是字符的组合,它们都有含义。我们可以暂时称它为字典。

接下来,我有多个这样的字符数组列表:

string[] charArr1 = "a,j,s".Split(',');
string[] charArr2 = "c,l,o".Split(',');
string[] charArr3 = "d,m,n".Split(',');
string[] charArr4 = "n,e,w".Split(',');
string[] charArr5 = "f,o,x".Split(',');
string[] charArr6 = "h,q,z".Split(',');
string[] charArr7 = "i,r".Split(',');

我想将字符连接在一起。对于每个 charArray,我将取出 1 个字符并将它们连接在一起成为单词,然后我将检查这些连接的单词是否在 listwords[] 列表中。如果存在,我会将单词保存在 saveWords[] 数组中。 条件:

  • 同一个 charArray[] 的字符不连接在一起,每个 charArray[] 每次只能选择一个字符。
  • 匹配所有案例,不错过任何案例。

例如:

  • a+c -> ac(匹配正确)-> 在 listwords[] 中搜索 -> 不出现
  • a+j(匹配不当)
  • a+s(匹配不当)
  • a+c+d -> acd(正确匹配)-> 在 listwords[] 中搜索 -> 不出现
  • s+e+i+h -> seih(匹配正确)-> 在 listwords[] 中搜索 -> 不出现
  • s+e+h+i -> sehi (匹配正确) -> 在 listwords[] 中搜索 -> 如果这个词出现 -> 保存到 saveWords[] 数组

我的意思是字符的连接不会漏掉任何大小写。例如:

  • charArr1[]+charArr2[] -> 将匹配以下情况:a+c, a+l, a+o, j+c, j+l, j+o, s+c, s+l, s+o
  • charArr2[]+charArr1[] -> 将匹配以下情况:c+a, c+j, c+s, l+a,l+j, l+s,o+a,o+j, o+s
  • charArr1+charArr2+charArr3
  • charArr1[]+charArr3[]+charArr2[]
  • charArr2[]+charArr1[]+charArr3[]
  • charArr2[]+charArr3[]+charArr1[]
  • 等等……

请帮助我,因为我对算法感到困惑。非常感谢。

【问题讨论】:

  • 在您的第五个示例 s+e+i+h(正确匹配)之前,我以为我理解了您要做什么。我看不出你如何通过做我认为你正在做的事情来获得 s+e+i+h,因为最后一个可用的“h”在 charArray6 中,直到 charArray7 才出现“i”。
  • 感谢您回答我的问题。这个问题很难解释。我已经编辑了以上内容,以便您更轻松地进行可视化。

标签: c# arrays algorithm concatenation


【解决方案1】:

给定

public static IEnumerable<string[]> Permutate(string[] array, int i, int n)
{
   if (i == n)
      yield return array;
   else
      for (var j = i; j <= n; j++)
      {
         Swap(ref array[i], ref array[j]);

         foreach (var s in Permutate(array, i + 1, n))
            yield return s;

         Swap(ref array[i], ref array[j]);
      }
}

public static void Swap(ref string a, ref string b) => (a, b) = (b, a);

public static bool IncMask(string[][] source, int[] mask)
{
   for (var i = 0; i < mask.Length; i++)
   {
      mask[i]++;
      if (mask[i] > source[i].Length)
         mask[i] = 0;
      else
         return false;
   }

   return true;
}

public static IEnumerable<string> Iterate(params string[][] source)
{
   var masks = new int[source.Length];

   while (true)
   {

      if (IncMask(source, masks))
         break;

      var array = masks
         .Select((i, j) => (i, j))
         .Where(x => x.i != 0)
         .Select(x => source[x.j][x.i - 1])
         .ToArray();

      foreach (var result in Permutate(array, 0, array.Length - 1))
         yield return string.Concat(result);

   }
}

用法

var listWords = "la,lam,lan,son,som,some,mos,mao,sehi,noesrh,nroeh,doise".Split(',');

var charArr1 = "a,j,s".Split(',');
var charArr2 = "c,l,o".Split(',');
var charArr3 = "d,m,n".Split(',');
var charArr4 = "n,e,w".Split(',');
var charArr5 = "f,o,x".Split(',');
var charArr6 = "h,q,z".Split(',');
var charArr7 = "i,r".Split(',');

var results = Iterate(charArr1, charArr2, charArr3, charArr4, charArr5, charArr6, charArr7)
   .Where(x => listWords.Contains(x));

Console.WriteLine(string.Join(", ", results));

结果

la, lam, mao, som, mos, lan, son, lan, son, some, mao, som, mos, son, son, some, doise, doise, sehi, nroeh, noesrh, nroeh, noesrh

注意,这是一个计算量相当大的问题,我没有花太多精力来提高效率,也不关心重复。它可能可以通过许多其他(更高性能)的方式来解决。 此外,我只对此进行了最低限度的测试,因此我不对您因此代码而致残或以其他方式伤害的任何人负责。这可能是完全错误的¯\_(ツ)_/¯

【讨论】:

  • 哇,你真令人印象深刻。我对你的技能感到惊讶。在很短的时间内,您可以想出一个解决方案来支持自己。真诚的感谢。
  • 请帮我检查一遍。使用您的代码时,它会在此处引发错误:“.Where (x => xi! = 0)”错误代码:CS1061 '(int, int)' does not contain a definition for 'i' and no extension method 'i ' 接受'(int, int)' 类型的第一个参数(您是否缺少参考使用显示或程序集?) test c:\users\admin\Documents\visual studio 2017\Projects\test\test\Form1.cs 80
  • @nanocovax 那里不应该有错误,它可能是您使用的框架,听起来元组有问题,您使用的是 .net 5 吗?
  • 我使用 .net 4.7。 :(你能建议我使用哪个版本吗?非常感谢
  • @nanocovax 如果您使用 .net 5.0,这一切都会奏效。 .net 框架有点旧,如果你不能使用 .net 5.0,请告诉我,我会给你兼容的代码
猜你喜欢
  • 1970-01-01
  • 2013-12-25
  • 2021-08-18
  • 1970-01-01
  • 2018-08-15
  • 1970-01-01
  • 2021-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多