Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 向要显示的项目列表添加分隔符_C#_Algorithm - Fatal编程技术网

C# 向要显示的项目列表添加分隔符

C# 向要显示的项目列表添加分隔符,c#,algorithm,C#,Algorithm,我有一个要显示的项目列表,它们之间用C#分隔。使用普通迭代器,我将在开始或结束时使用一个额外的分隔符: string[] sa = {"one", "two", "three", "four"}; string ns = ""; foreach(string s in sa) { ns += s + " * "; } // ns has a trailing *: // one * two * three * four * 现在我可以使用for循环解决这个问题,如下所示: ns =

我有一个要显示的项目列表,它们之间用C#分隔。使用普通迭代器,我将在开始或结束时使用一个额外的分隔符:

string[] sa = {"one", "two", "three", "four"};
string ns = "";
foreach(string s in sa)
{
    ns += s + " * ";
}
// ns has a trailing *:
// one * two * three * four * 
现在我可以使用for循环解决这个问题,如下所示:

ns = "";
for(int i=0; i<sa.Length; i++)
{
    ns += sa[i];
    if(i != sa.Length-1)
        ns += " * ";
}
// this works:
// one * two * three * four
ns=”“;
对于(int i=0;i您需要内置方法:

如果要对其他集合类型执行相同的操作,则如果首先使用LINQ的方法创建数组,则仍然可以使用
String.Join


这种方法的优点是可以在任何类型的序列上使用它,而不仅仅是字符串数组

var ns = sa.Aggregate( (c, s) => c + " * " + s);

我更喜欢卢克的解决方案

string ns = string.Join(" * ", sa);
或者,如果您的集合不是可索引的,而是可枚举的,则可以执行此操作:

string ns = "";
foreach(string s in sa)
{
    if (ns.Length != 0)
    {
        ns += " * ";
    }

    ns += s;
}

这与第二个示例类似,但它将测试放在循环的开始,并且不太可能出现第二个示例中可能出现的一次性错误。数组显然是可索引的,但在某些情况下会得到容器(即System.Collections.Generic.Dictionary.Values)这是不可索引的,你会想要这样的东西。

< P>除了优雅之外,你还需要考虑不同于字符串的类型的速度和可重用性。对于优雅,我建议使用扩展方法来抽象细节,以便普通用法看起来像:

ns = sa.Join(" * ");
<速度>考虑下面的变型测试,包括一些已经回答了问题的人提出的一些解决方案:

public void Test_variants()
{
    const string item = "a";
    const int numberOfTimes = 100000;
    const string delimiter = ", ";
    string[] items = new List<string>(Enumerable.Repeat(item, numberOfTimes)).ToArray();
    string expected = String.Join(delimiter, items);

    Time(StringJoin, items, delimiter, expected);
    Time(Aggregate, items, delimiter, expected);
    Time(CheckForEndInsideLoop_String, items, delimiter, expected);
    Time(CheckForBeginningInsideLoop_String, items, delimiter, expected);
    Time(RemoveFinalDelimiter_String, items, delimiter, expected);
    Time(CheckForEndInsideLoop_StringBuilder, items, delimiter, expected);
    Time(RemoveFinalDelimiter_StringBuilder, items, delimiter, expected);
}

private static void Time(Func<string[], string, string> func, string[] items, string delimiter, string expected)
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    string result = func(items, delimiter);
    stopwatch.Stop();
    bool isValid = result == expected;
    Console.WriteLine("{0}\t{1}\t{2}", stopwatch.Elapsed, isValid, func.Method.Name);
}

private static string CheckForEndInsideLoop_String(string[] items, string delimiter)
{
    string result = "";
    for (int i = 0; i < items.Length; i++)
    {
        result += items[i];
        if (i != items.Length - 1)
        {
            result += delimiter;
        }
    }
    return result;
}

private static string RemoveFinalDelimiter_String(string[] items, string delimiter)
{
    string result = "";
    for (int i = 0; i < items.Length; i++)
    {
        result += items[i] + delimiter;
    }
    return result.Substring(0, result.Length - delimiter.Length);
}

private static string CheckForBeginningInsideLoop_String(string[] items, string delimiter)
{
    string result = "";
    foreach (string s in items)
    {
        if (result.Length != 0)
        {
            result += delimiter;
        }
        result += s;
    }
    return result;
}

private static string CheckForEndInsideLoop_StringBuilder(string[] items, string delimiter)
{
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < items.Length; i++)
    {
        result.Append(items[i]);
        if (i != items.Length - 1)
        {
            result.Append(delimiter);
        }
    }
    return result.ToString();
}

private static string RemoveFinalDelimiter_StringBuilder(string[] items, string delimiter)
{
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < items.Length; i++)
    {
        result.Append(items[i]);
        result.Append(delimiter);
    }
    result.Length = result.Length - delimiter.Length;
    return result.ToString();
}

private static string StringJoin(string[] items, string delimiter)
{
    return String.Join(delimiter, items);
}

private static string Aggregate(string[] items, string delimiter)
{
    return items.Aggregate((c, s) => c + delimiter + s);
}

Joe,既然您使用的是LINQ,那么如果您从序列中创建一个数组,然后使用String.Join,您将获得更好的性能和更可读的代码。例如:String.Join(“*”,test.ToArray());是的,可以从一个对象序列将某个字段投影到一个字符串序列,然后使用您的方法。我不知道字符串。Join before-一个说明LINQ不是万能药的完美示例:)+1,扩展方法非常适合于此。在回答另一个问题时,我发布了一个类似的例子,它也将转换器函数作为参数:
ns = sa.Join(" * ");
public void Test_variants()
{
    const string item = "a";
    const int numberOfTimes = 100000;
    const string delimiter = ", ";
    string[] items = new List<string>(Enumerable.Repeat(item, numberOfTimes)).ToArray();
    string expected = String.Join(delimiter, items);

    Time(StringJoin, items, delimiter, expected);
    Time(Aggregate, items, delimiter, expected);
    Time(CheckForEndInsideLoop_String, items, delimiter, expected);
    Time(CheckForBeginningInsideLoop_String, items, delimiter, expected);
    Time(RemoveFinalDelimiter_String, items, delimiter, expected);
    Time(CheckForEndInsideLoop_StringBuilder, items, delimiter, expected);
    Time(RemoveFinalDelimiter_StringBuilder, items, delimiter, expected);
}

private static void Time(Func<string[], string, string> func, string[] items, string delimiter, string expected)
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    string result = func(items, delimiter);
    stopwatch.Stop();
    bool isValid = result == expected;
    Console.WriteLine("{0}\t{1}\t{2}", stopwatch.Elapsed, isValid, func.Method.Name);
}

private static string CheckForEndInsideLoop_String(string[] items, string delimiter)
{
    string result = "";
    for (int i = 0; i < items.Length; i++)
    {
        result += items[i];
        if (i != items.Length - 1)
        {
            result += delimiter;
        }
    }
    return result;
}

private static string RemoveFinalDelimiter_String(string[] items, string delimiter)
{
    string result = "";
    for (int i = 0; i < items.Length; i++)
    {
        result += items[i] + delimiter;
    }
    return result.Substring(0, result.Length - delimiter.Length);
}

private static string CheckForBeginningInsideLoop_String(string[] items, string delimiter)
{
    string result = "";
    foreach (string s in items)
    {
        if (result.Length != 0)
        {
            result += delimiter;
        }
        result += s;
    }
    return result;
}

private static string CheckForEndInsideLoop_StringBuilder(string[] items, string delimiter)
{
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < items.Length; i++)
    {
        result.Append(items[i]);
        if (i != items.Length - 1)
        {
            result.Append(delimiter);
        }
    }
    return result.ToString();
}

private static string RemoveFinalDelimiter_StringBuilder(string[] items, string delimiter)
{
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < items.Length; i++)
    {
        result.Append(items[i]);
        result.Append(delimiter);
    }
    result.Length = result.Length - delimiter.Length;
    return result.ToString();
}

private static string StringJoin(string[] items, string delimiter)
{
    return String.Join(delimiter, items);
}

private static string Aggregate(string[] items, string delimiter)
{
    return items.Aggregate((c, s) => c + delimiter + s);
}
00:00:00.0027745 True StringJoin 00:00:24.5523967 True Aggregate 00:00:47.8091632 True CheckForEndInsideLoop_String 00:00:47.4682981 True CheckForBeginningInsideLoop_String 00:00:23.7972864 True RemoveFinalDelimiter_String 00:00:00.0076439 True CheckForEndInsideLoop_StringBuilder 00:00:00.0052803 True RemoveFinalDelimiter_StringBuilder 00:00:00.0001788 True StringJoin 00:00:00.0014983 True Aggregate 00:00:00.0001666 True CheckForEndInsideLoop_String 00:00:00.0002202 True CheckForBeginningInsideLoop_String 00:00:00.0002061 True RemoveFinalDelimiter_String 00:00:00.0002663 True CheckForEndInsideLoop_StringBuilder 00:00:00.0002278 True RemoveFinalDelimiter_StringBuilder
public static string Join<T>([CanBeNull] this IEnumerable<T> items, [CanBeNull] string delimiter)
{
    StringBuilder result = new StringBuilder();
    if (items != null && items.Any())
    {
        delimiter = delimiter ?? "";
        foreach (T item in items)
        {
            result.Append(item);
            result.Append(delimiter);
        }
        result.Length = result.Length - delimiter.Length;
    }
    return result.ToString();
}
ns = sa.Join(" * ");