查找具有特定汉明距离的字符串LINQ

时间:2016-05-28 12:01:42

标签: c# linq string-matching hamming-distance

如果我们运行以下命令(感谢@octavioccl寻求帮助)LINQ查询:

var result = stringsList
.GroupBy(s => s)
  .Where(g => g.Count() > 1)        
  .OrderByDescending(g => g.Count())
  .Select(g => g.Key);

它为我们提供了至少两次出现在列表中的所有字符串(但完全匹配,即汉明距离= 0 )。

我只是想知道是否有一个优雅的解决方案( 我迄今为止尝试过的所有解决方案要么使用循环还是一个丑陋的计数器或正则表达式 )可以在Where子句中指定汉明距离来获取那些位于指定汉明距离范围内的字符串吗?

P.S:所有字符串长度相等

更新

非常感谢krontogiannis的详细解答。正如我之前提到的,我希望获得汉明距离低于给定阈值的字符串列表。他的代码完全正常(再次感谢)。

唯一剩下的就是从字符串中取出字符串'结果集'并插入/添加到`List'

基本上这就是我想要的:

List<string> outputList = new List<string>();
foreach (string str in patternsList)
            {
                var rs = wordsList
    .GroupBy(w => hamming(w, str))
    .Where(h => h.Key <= hammingThreshold)
    .OrderByDescending(h => h.Key)
    .Select(h => h.Count());
outputList.Add(rs); //I know it won't work but just to show what is needed
            }

由于

2 个答案:

答案 0 :(得分:4)

使用LINQ计算两个字符串之间的汉明距离可以优雅地完成:

Func<string, string, int> hamming = (s1, s2) => s1.Zip(s2, (l, r) => l - r == 0 ? 0 : 1).Sum();

你对'分组'的问题有点模糊。你可以看到计算汉明距离你需要两个字符串。因此,您需要计算字符串列表中所有单词与输入的汉明距离,或者计算列表中单词之间的距离(或者您需要告诉我们的不同内容:-))。

无论如何,我会给出两个输入的例子

var words = new[] {
    "hello",
    "rellp",
    "holla",
    "fooba",
    "hempd"
};

案例1

var input = "hello";
var hammingThreshold = 3;

var rs = words
    .GroupBy(w => hamming(w, input))
    .Where(h => h.Key <= hammingThreshold)
    .OrderByDescending(h => h.Key);

输出类似于

hempd with distance 3
rellp holla with distance 2
hello with distance 0

案例2

var hs = words
    .SelectMany((w1, i) => 
        words
            .Where((w2, j) => i > j)
            .Select(w2 => new { Word1 = w1, Word2 = w2 })) // all word pairs except with self
    .GroupBy(pair => hamming(pair.Word1, pair.Word2))
    .Where(g => g.Key <= hammingThreshold)
    .OrderByDescending(g => g.Key);

输出类似于

(holla, rellp) (fooba, holla) (hempd, hello) with distance 3
(rellp, hello) (holla, hello) with distance 2

修改要仅获取第一个分组中的字词,您可以使用SelectMany

var output = rs.SelectMany(g => g).ToList();

答案 1 :(得分:-1)

你可以这样做:

int hammingDistance = 2;
var result = stringsList
.GroupBy(s => s.Substring(0, s.Length - hammingDistance))
.Where(g => g.Count() > 1)
.OrderbyDescending(g => g.Count())
.Select(g => g.Key);