在字符串c#中分组字符的有效方法

时间:2018-03-14 00:57:08

标签: c# linq grouping

我想要一种有效的方法来对字符串进行分组,同时保持重复和顺序。 像这样的东西

1100110002200   -> 101020

我之前试过这个

_case.GroupBy(c => c).Select(g => g.Key)

但我得到了102

但是这给了我想要的东西,我只是想优化它,所以我不必每次都搜索整个列表

static List<char> group(string _case)
{
    var groups = new List<char>();
    for (int i = 0; i < _case.Length; i++)
    {
        if (groups.LastOrDefault() != _case[i])
            groups.Add(_case[i]);
    }
    return groups;
}

2 个答案:

答案 0 :(得分:4)

您可以创建一个循环每个字符并检查前一个字符是否相等的方法。如果它们不相同,则追加/ yield返回该字符。 Linq很容易做到这一点。

public static string Simplify(string str)
{
    return string.Concat(str.Where((c, i) => i == 0 || c != str[i - 1]));
}

用法:

string simplified = Simplify("1100110002200");
// 101020

在我的测试中,我的方法和你的方法在速度方面大致相等,在执行了1000万次后(4260毫秒对4241毫秒),我的方法速度微不足道。

但是,我的方法将结果作为字符串返回,而不是。如果你需要将结果转换回字符串(很可能),那么我的方法确实更快/更有效(4260ms vs 6569ms)。

答案 1 :(得分:4)

虽然我喜欢rshepp的优雅解决方案,但事实证明,基本代码的运行速度甚至可以快5倍。

public static string Simplify2(string str)
{
    if (string.IsNullOrEmpty(str)) { return str; }

    StringBuilder sb = new StringBuilder();
    char last = str[0];
    sb.Append(last);

    foreach (char c in str)
    {
        if (last != c)
        {
            sb.Append(c);
            last = c;
        }
    }

    return sb.ToString();
}