繁体   English   中英

具有公共前缀的字符串组列表

[英]Group list of strings with common prefixes

假设我有一个字符串列表[city01, city01002, state02, state03, city04, statebg, countryqw, countrypo]

我如何将它们分组在<string, List<Strings>>dictionary

city - [city01, city04, city01002]
state- [state02, state03, statebg]
country - [countrywq, countrypo]

如果不是代码,任何人都可以帮助了解如何接近或继续吗?

您可以使用 LINQ:

 var input = new List<string>()
{ "city01", "city01002", "state02",
   "state03", "city04", "statebg", "countryqw", "countrypo" };

var output = input.GroupBy(c => string.Join("", c.TakeWhile(d => !char.IsDigit(d))
            .Take(4))).ToDictionary(c => c.Key, c => c.ToList());

如其他答案所示,您可以使用 LINQ 中的 GroupBy 方法根据您想要的任何条件创建此分组。 在对字符串进行分组之前,您需要了解字符串分组方式的条件。 可能是它以一组预定义前缀中的一个开头,按第一个数字之前的内容或您可以用代码描述的任何随机条件分组。 在我的代码示例中, groupBy 方法为列表中的每个字符串调用另一个方法,在该方法中,您可以通过返回键来根据需要对字符串进行分组,从而将给定的字符串分组到其下。 您可以使用 dotnetfiddle 在线测试此示例: https ://dotnetfiddle.net/UHNXvZ

using System;
using System.Collections.Generic;
using System.Linq;
                
public class Program
{
    public static void Main()
    {
        List<string> ungroupedList = new List<string>() {"city01", "city01002", "state02", "state03", "city04", "statebg", "countryqw", "countrypo", "theFirstTown"};
        var groupedStrings = ungroupedList.GroupBy(x => groupingCondition(x));
    
        foreach (var a in groupedStrings) {
            Console.WriteLine("key: " + a.Key);
            foreach (var b in a) {
                Console.WriteLine("value: " + b);
            }
        }
    }

    public static string groupingCondition(String s) {
        if(s.StartsWith("city") || s.EndsWith("Town"))
            return "city";
        if(s.StartsWith("country"))
            return "country";
        if(s.StartsWith("state"))
            return "state";
        return "unknown";
    }
}

我想你有一个你在列表中搜索的参考列表:

    var list = new List<string>()
    { "city01", "city01002", "state02",
        "state03", "city04", "statebg", "countryqw", "countrypo" };

    var tofound = new List<string>() { "city", "state", "country" }; //references to found
    

    var result = new  Dictionary<string, List<string>>();
    foreach (var f in tofound)
    {
        result.Add(f, list.FindAll(x => x.StartsWith(f)));
    }

结果,您得到了想要的字典。 如果没有为引用键建立值,则键的值为空

警告:此答案具有组合扩展,如果您的原始字符串集很大,则会失败。 跑了几个小时后,我放弃了 65 个单词。

使用一些IEnumerable扩展方法来查找Distinct集合并找到所有可能的集合组合,您可以生成一组前缀,然后通过这些前缀对原始字符串进行分组。

public static class IEnumerableExt {
    public static bool IsDistinct<T>(this IEnumerable<T> items) {
        var hs = new HashSet<T>();
        foreach (var item in items)
            if (!hs.Add(item))
                return false;

        return true;
    }

    public static bool IsEmpty<T>(this IEnumerable<T> items) => !items.Any();

    public static IEnumerable<IEnumerable<T>> AllCombinations<T>(this IEnumerable<T> start) {
        IEnumerable<IEnumerable<T>> HelperCombinations(IEnumerable<T> items) {
            if (items.IsEmpty())
                yield return items;
            else {
                var head = items.First();
                var tail = items.Skip(1);
                foreach (var sequence in HelperCombinations(tail)) {
                    yield return sequence; // Without first
                    yield return sequence.Prepend(head);
                }
            }
        }

        return HelperCombinations(start).Skip(1); // don't return the empty set
    }
}

var keys = Enumerable.Range(0, src.Count - 1)
            .SelectMany(n1 => Enumerable.Range(n1 + 1, src.Count - n1 - 1).Select(n2 => new { n1, n2 }))
            .Select(n1n2 => new { s1 = src[n1n2.n1], s2 = src[n1n2.n2], Dist = src[n1n2.n1].TakeWhile((ch, n) => n < src[n1n2.n2].Length && ch == src[n1n2.n2][n]).Count() })
            .SelectMany(s1s2d => new[] { new { s = s1s2d.s1, s1s2d.Dist }, new { s = s1s2d.s2, s1s2d.Dist } })
            .Where(sd => sd.Dist > 0)
            .GroupBy(sd => sd.s.Substring(0, sd.Dist))
            .Select(sdg => sdg.Distinct())
            .AllCombinations()
            .Where(sdgc => sdgc.Sum(sdg => sdg.Count()) == src.Count)
            .Where(sdgc => sdgc.SelectMany(sdg => sdg.Select(sd => sd.s)).IsDistinct())
            .OrderByDescending(sdgc => sdgc.Sum(sdg => sdg.First().Dist)).First()
            .Select(sdg => sdg.First())
            .Select(sd => sd.s.Substring(0, sd.Dist))
            .ToList();

var groups = src.GroupBy(s => keys.First(k => s.StartsWith(k)));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM