使用分隔符连接字符串

30

如何将字符串列表连接成一个以分隔符为分隔的字符串?主要关注何时停止添加分隔符,使用C#举例,但希望这个方法是语言无关的。

编辑:我没有使用 StringBuilder,让代码更简单一些。

使用 For 循环

for(int i=0; i < list.Length; i++)
{
    result += list[i];
    if(i != list.Length - 1)
        result += delimiter;
}

使用for循环并设置先前的第一个项目

result = list[0];
for(int i = 1; i < list.Length; i++)
    result += delimiter + list[i];

如果你不预先知道列表的长度,这些方法在 IEnumerable 上将不起作用,所以

使用 foreach 循环

bool first = true;
foreach(string item in list)
{
    if(!first)
        result += delimiter;
    result += item;
    first = false;
}

foreach循环的变化

来自Jon的解决方案。

StringBuilder builder = new StringBuilder();
string delimiter = "";
foreach (string item in list)
{
    builder.Append(delimiter);
    builder.Append(item);
    delimiter = ",";       
}
return builder.ToString();

使用迭代器

再次来自Jon

using (IEnumerator<string> iterator = list.GetEnumerator())
{
    if (!iterator.MoveNext())
        return "";
    StringBuilder builder = new StringBuilder(iterator.Current);
    while (iterator.MoveNext())
    {
        builder.Append(delimiter);
        builder.Append(iterator.Current);
    }
    return builder.ToString();
}

还有哪些其他算法?


在你的foreach循环中,不要忘记将first设置为false。 - tehvan
如果您希望这是语言无关的,那么您不应该担心C#特定的优化(例如StringBuilder)。 - mpen
25个回答

1
在Java 8中,我们可以使用:


List<String> list = Arrays.asList(new String[] { "a", "b", "c" });
System.out.println(String.join(",", list)); //Output: a,b,c

要添加前缀和后缀,我们可以这样做:

StringJoiner joiner = new StringJoiner(",", "{", "}");
list.forEach(x -> joiner.add(x));
System.out.println(joiner.toString()); //Output: {a,b,c}

在Java 8之前,您可以像Jon的答案一样操作。
StringBuilder sb = new StringBuilder(prefix);
boolean and = false;
for (E e : iterable) {        
    if (and) {
        sb.append(delimiter);
    }
    sb.append(e);
    and = true;
}
sb.append(suffix);

1

看到了Python的答案3次,但没有Ruby?!?!

代码的第一部分声明了一个新数组。然后你可以调用.join()方法并传递分隔符,它将返回一个带有分隔符的字符串。我相信join方法在连接之前会调用每个项的.to_s方法。

["ID", "Description", "Active"].join(",")
>> "ID, Description, Active"

当结合元编程和数据库交互时,这非常有用。

有人知道C#是否有类似于这种语法糖的东西吗?


1

这就是 Python 解决问题的方式:

','.join(list_of_strings)

虽然我从来没有理解在琐碎的情况下需要“算法”的必要性


不,那是你在Python中如何“编写”它。要了解Python如何“解决”问题,您需要查看join的实现,然后在那里找到一个算法。 - Svante
不,这就是Python为我解决这个问题的方式。我不需要发明任何算法,因为Python为我提供了一种惯用的内置方法。Python实现使用哪种算法在这里没有任何相关性。 - SilentGhost
问题是关于算法的。作为原帖发布者,我也不会对“我打电话给Bob,他可以用Blub编写它”的回答感兴趣。 - Svante
顺便说一下,我不明白为什么你要回滚到错误的语法和拼写。这是自尊心问题吗?现在你只能忍受它了。 - Svante
嗯,这是用Python编写的算法。并不是我的错,有些语言就是愚蠢。我的语法和拼写没有任何问题,非常感谢。 - SilentGhost

1

这是一个C#的可行解决方案,在Java中,您可以在迭代器上使用类似的for each。

        string result = string.Empty; 

        // use stringbuilder at some stage.
        foreach (string item in list)
            result += "," + item ;

        result = result.Substring(1);
        // output:  "item,item,item"

如果使用.NET,您可能希望使用扩展方法,这样您就可以执行list.ToString(",")。详情请参阅为数组、列表、字典、通用IEnumerable设置分隔符转换字符串
// contains extension methods, it must be a static class.
public static class ExtensionMethod
{
    // apply this extension to any generic IEnumerable object.
    public static string ToString<T>(this IEnumerable<T> source,
      string separator)
    {
        if (source == null)
           throw new ArgumentException("source can not be null.");

        if (string.IsNullOrEmpty(separator))
           throw new ArgumentException("separator can not be null or empty.");

        // A LINQ query to call ToString on each elements
        // and constructs a string array.
        string[] array =
         (from s in source
          select s.ToString()
          ).ToArray();

        // utilise builtin string.Join to concate elements with
        // customizable separator.
        return string.Join(separator, array);
    }
}

编辑:出于性能考虑,请使用本主题中提到的字符串构建器解决方案替换连接代码。


1
使用字符串连接(如第一个示例)极其低效。在Java和.NET中,请使用StringBuilder。 - Jon Skeet
@Jon,顺便提一下第一个示例上面有评论。 - Ray Lu

1

我认为做这样的事情最好的方法是(我将使用伪代码,以便我们真正做到语言无关):

function concat(<array> list, <boolean> strict):
  for i in list:
    if the length of i is zero and strict is false:
      continue;
    if i is not the first element:
      result = result + separator;
    result = result + i;
  return result;

concat() 的第二个参数 strict 是一个标志,用于确定是否在连接时考虑空字符串。

我习惯于不考虑追加最后的分隔符;另一方面,如果 strict 为 false,则结果字符串可能不包含像 "A,B,,,F" 这样的内容,前提是分隔符是逗号,而是呈现为 "A,B,F"。


1

既然你标记了这个语言无关的话题,

以下是如何在Python中实现的。

# delimiter can be multichar like "| trlalala |"
delimiter = ";"
# sequence can be any list, or iterator/generator that returns list of strings
result = delimiter.join(sequence)
#result will NOT have ending delimiter 

编辑:看来我的回答被好几个人抢先了。对于重复回答我感到抱歉。


0
这是我的谦虚尝试;
public static string JoinWithDelimiter(List<string> words, string delimiter){
    string joinedString = "";
    if (words.Count() > 0)
    {
        joinedString = words[0] + delimiter;
        for (var i = 0; i < words.Count(); i++){
            if (i > 0 && i < words.Count()){
                if (joinedString.Length > 0)
                {
                    joinedString += delimiter + words[i] + delimiter;
                } else {
                    joinedString += words[i] + delimiter;
                }
            }
        }
    }
    return joinedString;
}

用法:

List<string> words = new List<string>(){"my", "name", "is", "Hari"};
Console.WriteLine(JoinWithDelimiter(words, " "));

0
在Java中,这个问题或这个问题都已经给出了非常完整的答案。
也可以使用Apache Commons中的StringUtils.join函数。
String result = StringUtils.join(list, ", ");

0
在Clojure中,您可以直接使用clojure.contrib.str-utils/str-join:
(str-join ", " list)

但是对于实际的算法:

(reduce (fn [res cur] (str res ", " cur)) list)

0
string result = "";
foreach(string item in list)
{
    result += delimiter + item;
}
result = result.Substring(1);

编辑:当然,您不会使用此算法或任何其他算法来连接字符串。在C#/.NET中,您可能会使用StringBuilder:

StringBuilder sb = new StringBuilder();
foreach(string item in list)
{
    sb.Append(delimiter);
    sb.Append(item);
}
string result = sb.ToString(1, sb.Length-1);

还有一种解决方案的变体:

StringBuilder sb = new StringBuilder(list[0]);
for (int i=1; i<list.Count; i++)
{
    sb.Append(delimiter);
    sb.Append(list[i]);
}
string result = sb.ToString();

两种解决方案都没有包含任何错误检查。


这非常低效 - 至少在C#中是这样的 - 因为它每次都会复制“到目前为止的字符串”。 - Jon Skeet
我知道这是低效的(我会使用StringBuilder)。但那不是问题。 - M4N
1
问题是关于最佳方法的。 "极其低效"和"最佳"通常不会同时出现。 - Jon Skeet
为什么不使用StringBuilder编辑答案?在我看来,这个整体概念是与语言无关的,所以至少给出一个适用于C#的答案 :) - Jon Skeet
这仍然涉及到一个无意义的复制 - 因此我采取了不同的方法 :) - Jon Skeet
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接