string 使用分隔符连接字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/581448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:23:13  来源:igfitidea点击:

Join a string using delimiters

algorithmlanguage-agnosticstring

提问by John Oxley

What is the best way to join a list of strings into a combined delimited string. I'm mainly concerned about when to stop adding the delimiter. I'll use C# for my examples but I would like this to be language agnostic.

将字符串列表加入组合分隔字符串的最佳方法是什么。我主要关心什么时候停止添加分隔符。我将在示例中使用 C#,但我希望它与语言无关。

EDIT: I have not used StringBuilder to make the code slightly simpler.

编辑:我没有使用 StringBuilder 使代码稍微简单一些。

Use a For Loop

使用 For 循环

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

Use a For Loop setting the first item previously

使用 For 循环设置之前的第一项

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

These won't work for an IEnumerable where you don't know the length of the list beforehand so

这些不适用于您事先不知道列表长度的 IEnumerable

Using a foreach loop

使用 foreach 循环

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

Variation on a foreach loop

foreach 循环的变化

From Jon's solution

来自乔恩的解决方案

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

Using an Iterator

使用迭代器

Again from 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();
}

What other algorithms are there?

还有哪些算法?

回答by Jon Skeet

It's impossible to give a truly language-agnostic answer here as different languages and platforms handle strings differently, and provide different levels of built-in support for joining lists of strings. You could take pretty much identicalcode in two different languages, and it would be great in one and awful in another.

由于不同的语言和平台以不同的方式处理字符串,并为连接字符串列表提供不同级别的内置支持,因此这里不可能给出真正与语言无关的答案。你可以用两种不同的语言编写几乎相同的代码,用一种很好,用另一种很糟糕。

In C#, you could use:

在 C# 中,您可以使用:

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

This will prependa comma on all but the first item. Similar code would be good in Java too.

这将预先准备的所有逗号,但第一个项目。类似的代码在 Java 中也很好。

EDIT: Here's an alternative, a bit like Ian's later answer but working on a general IEnumerable<string>.

编辑:这是一个替代方案,有点像伊恩后来的回答,但在一般 IEnumerable<string>.

// Change to IEnumerator for the non-generic IEnumerable
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();
}

EDIT nearly 5 years after the original answer...

在原始答案后近 5 年编辑...

In .NET 4, string.Joinwas overloaded pretty significantly. There's an overload taking IEnumerable<T>which automatically calls ToString, and there's an overload for IEnumerable<string>. So you don't need the code above any more... for .NET, anyway.

在 .NET 4 中,string.Join重载非常显着。有一个IEnumerable<T>自动调用ToString的重载,并且有一个 的重载IEnumerable<string>。所以你不再需要上面的代码......对于.NET,无论如何。

回答by Ian Nelson

In .NET, you can use the String.Join method:

在 .NET 中,您可以使用String.Join 方法

string concatenated = String.Join(",", list.ToArray());

Using .NET Reflector, we can find out how it does it:

使用.NET Reflector,我们可以了解它是如何做到的:

public static unsafe string Join(string separator, string[] value, int startIndex, int count)
{
    if (separator == null)
    {
        separator = Empty;
    }
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }
    if (startIndex < 0)
    {
        throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
    }
    if (count < 0)
    {
        throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
    }
    if (startIndex > (value.Length - count))
    {
        throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
    }
    if (count == 0)
    {
        return Empty;
    }
    int length = 0;
    int num2 = (startIndex + count) - 1;
    for (int i = startIndex; i <= num2; i++)
    {
        if (value[i] != null)
        {
            length += value[i].Length;
        }
    }
    length += (count - 1) * separator.Length;
    if ((length < 0) || ((length + 1) < 0))
    {
        throw new OutOfMemoryException();
    }
    if (length == 0)
    {
        return Empty;
    }
    string str = FastAllocateString(length);
    fixed (char* chRef = &str.m_firstChar)
    {
        UnSafeCharBuffer buffer = new UnSafeCharBuffer(chRef, length);
        buffer.AppendString(value[startIndex]);
        for (int j = startIndex + 1; j <= num2; j++)
        {
            buffer.AppendString(separator);
            buffer.AppendString(value[j]);
        }
    }
    return str;
}

回答by Hank Gay

There's little reason to make it language-agnostic when some languages provide support for this in one line, e.g., Python's

当某些语言在一行中提供支持时,几乎没有理由使它与语言无关,例如 Python 的

",".join(sequence)

See the join documentationfor more info.

有关更多信息,请参阅加入文档

回答by Christian Witts

For python be sure you have a list of strings, else ','.join(x) will fail. For a safe method using 2.5+

对于 python,请确保您有一个字符串列表,否则 ','.join(x) 将失败。对于使用 2.5+ 的安全方法

delimiter = '","'
delimiter.join(str(a) if a else '' for a in list_object)

The "str(a) if a else ''" is good for None types otherwise str() ends up making then 'None' which isn't nice ;)

"str(a) if a else ''" 对 None 类型有好处,否则 str() 最终会变成 'None',这不好;)

回答by Jeremy L

In PHP's implode():

在 PHP 的implode() 中

$string = implode($delim, $array);

回答by eponie

List<string> aaa = new List<string>{ "aaa", "bbb", "ccc" };
string mm = ";";
return aaa.Aggregate((a, b) => a + mm + b);

and you get

你得到

aaa;bbb;ccc

lambda is pretty handy

lambda 非常方便

回答by Svante

I would express this recursively.

我会递归地表达这一点。

  • Check if the number of string arguments is 1. If it is, return it.
  • Otherwise recurse, but combine the first two arguments with the delimiter between them.
  • 检查字符串参数的数量是否为 1。如果是,则返回它。
  • 否则递归,但将前两个参数与它们之间的分隔符组合在一起。

Example in Common Lisp:

Common Lisp 中的示例:

(defun join (delimiter &rest strings)
  (if (null (rest strings))
      (first strings)
      (apply #'join
             delimiter
             (concatenate 'string
                          (first strings)
                          delimiter
                          (second strings))
             (cddr strings))))

The more idiomatic way is to use reduce, but this expands to almost exactly the same instructions as the above:

更惯用的方法是使用reduce,但这扩展为与上述指令几乎完全相同的指令:

(defun join (delimiter &rest strings)
  (reduce (lambda (a b)
            (concatenate 'string a delimiter b))
          strings))

回答by Svante

I'd always add the delimeter and then remove it at the end if necessary. This way, you're not executing an if statement for every iteration of the loop when you only care about doing the work once.

我总是添加分隔符,然后在必要时将其删除。这样,当您只关心完成一次工作时,您就不会为循环的每次迭代执行 if 语句。

StringBuilder sb = new StringBuilder();

foreach(string item in list){
    sb.Append(item);
    sb.Append(delimeter);
}

if (list.Count > 0) {
    sb.Remove(sb.Length - delimter.Length, delimeter.Length)
}

回答by Jonathan Campbell

The problem is that computer languages rarely have string booleans, that is, methods that are of type string that do anything useful. SQL Server at least has is[not]null and nullif, which when combined solve the delimiter problem, by the way: isnotnull(nullif(columnvalue, ""),"," + columnvalue))

问题是计算机语言很少有字符串布尔值,也就是说,字符串类型的方法可以做任何有用的事情。SQL Server至少有is[not]null和nullif,结合起来解决定界符问题,顺便说一句:isnotnull(nullif(columnvalue, ""),"," + columnvalue))

The problem is that in languages there are booleans, and there are strings, and never the twain shall meet except in ugly coding forms, e.g.

问题是在语言中有布尔值和字符串,除了丑陋的编码形式外,这两个词永远不会相遇,例如

concatstring = string1 + "," + string2; if (fubar) concatstring += string3 concatstring += string4 etc

concatstring = string1 + "," + string2; if (fubar) concatstring += string3 concatstring += string4 等等

I've tried mightily to avoid all this ugliness, playing comma games and concatenating with joins, but I'm still left with some of it, including SQL Server errors when I've missed one of the commas and a variable is empty.

我已经尽力避免所有这些丑陋,玩逗号游戏和连接连接,但我仍然留下了一些,包括当我错过了一个逗号并且变量为空时的 SQL Server 错误。

Jonathan

乔纳森

回答by vartec

In C# you can just use String.Join(separator,string_list)

在 C# 中你可以只使用String.Join(separator,string_list)