0

您知道采用逗号分隔的字符串(例如“A,B,C,D,E,F,G”)并仅返回列表中第一个 x 数量的项目的最佳/最干净的方法是什么?因此,如果 x = 5,那么结果将是“A、B、C、D、E”。

我知道有不同的方法可以做到这一点:“for循环”计数逗号,然后截断字符串;将字符串拆分为数组或列表,然后删除最后 x 个项目。

有没有我不知道的更清洁、更有效的选择?你会怎么做?

提前致谢!!格雷格

4

7 回答 7

5

我会将任务分为两部分:

  • 用逗号分割字符串
  • 只取前 N 个值

幸运的是,C# 使这两个都变得非常简单,String.Split处理第一个,而 LINQTake方法处理第二个:

var items = text.Split(',')
                .Take(itemLimit);

或者,如果您想创建一个列表:

var items = text.Split(',')
                .Take(itemLimit)
                .ToList();

除非您确实需要,否则我不会将其转换回逗号分隔的字符串。List<string>尽可能长时间地保持数据的最自然表示(例如 a )。如果需要,只需使用String.Join.

您可以通过编写“惰性拆分器”来提高该Split部分的效率 - 但 IMO 除非您希望得到一个很长的字符串并且只想保留一些项目,否则它只会获得很少的收益。它看起来这样:

public static IEnumerable<string> LazySplit(this string text, string separator)
{
    int start = 0;
    while (true)
    {
        int end = text.IndexOf(separator, start);
        if (end == -1)
        {
            // Note: if the string ends with the separator, this will yield
            // an empty string
            yield return text.Substring(start);
            yield break; // This will terminate the otherwise-infinite loop
        }
        yield return text.Substring(start, end - start);
        start = end + separator.Length;
    }
}

那么使用代码和之前类似:

var items = text.LazySplit(",")
                .Take(itemLimit)
                .ToList();

或者,如果你真的,真的需要把它保存在一个字符串中,你可以写一些东西来找到第 N 个逗号,然后用它Substring来获取字符串的第一部分:

// TODO: Improve the name :)
public static string TruncateAfterSeparatorCount(string text,
                                                 string separator,
                                                 int count)
{
    // We pretend that the string "starts" with a separator before index 0.
    int index = -separator.Length;
    for (int i = 0; i < count; i++)
    {
        int nextIndex = text.IndexOf(separator, index + separator.Length);
        // Not enough separators. Return the whole string. Could throw instead.
        if (nextIndex == -1)
        {
            return text;
        }
        index = nextIndex;
    }
    // We need to handle the count == 0 case, where index will be negative...
    return text.Substring(0, Math.Max(index, 0));
}

但正如我所说,如果可能的话,我个人会尝试使用这种List<string>方法。上面的代码显然比Split/ Take/复杂得多ToList,尽管它更有效。只有在证明有必要时才使用更高效但更复杂的代码。

于 2013-03-27T16:16:37.277 回答
3

试试这个:

string.Join("," , str.Split(",").Take(5));

或者,如果你经常这样做,你可以为此编写一个扩展方法。

于 2013-03-27T16:16:07.243 回答
0

大概是一个Split和一个Take

试试这个:

string yourString = "A,B,C,D,E,F,G";
List<string> items = yourString.Split(',')
    .Take(5)
    .ToList();
string output = string.Join(",", items);
于 2013-03-27T16:16:47.343 回答
0
string[] words = s.Split(',').Take(5);
于 2013-03-27T16:16:54.813 回答
0
    string[] List = SubList(5);
    string Output = string.Join(",", List);

private string[] SubList(int p)
{
    string[] List = new string[] { "A", "B", "C", "D", "E", "F" };
    string[] List2 = new string[p];
    for (int i = 0; i < p; i++)
        List2[i] = List[i];
    return List2;
}
于 2013-03-27T16:19:08.537 回答
0

如果您只想使用String方法(而不是 Take()),这应该可以工作:

string.Join(",", s.Split(","), 0, 5);

如果你知道每个元素只有一个字符,你可以这样做:

s.Substring(0, 2*x - 1);
于 2013-03-27T16:30:26.957 回答
0

只是为了好玩 - 仅使用 Regex/String 方法(我不会使用 Regex 来做这个现实世界 - 然后我会遇到两个问题):

string.SubString(0,Regex.Matches(string,",")[x-1].Index);
于 2013-03-27T16:34:58.007 回答