用于IEnumerable的String.Join(string,string [])的模拟

问题描述 投票:7回答:8

class String包含非常有用的方法 - String.Join(string, string[])

它从数组创建一个字符串,用给定的符号分隔数组的每个元素。但一般 - 它不会在最后一个元素后添加分隔符!我将它用于ASP.NET编码,用“<br />”或Environment.NewLine分隔。

所以我想在asp:Table的每一行之后添加一个空行。我可以使用什么方法来使用IEnumerable<TableRow>来实现相同的功能?

c# linq extension-methods ienumerable
8个回答
8
投票

我写了一个扩展方法:

    public static IEnumerable<T> 
        Join<T>(this IEnumerable<T> src, Func<T> separatorFactory)
    {
        var srcArr = src.ToArray();
        for (int i = 0; i < srcArr.Length; i++)
        {
            yield return srcArr[i];
            if(i<srcArr.Length-1)
            {
                yield return separatorFactory();
            }
        }
    }

您可以按如下方式使用它:

tableRowList.Join(()=>new TableRow())

8
投票

Linq相当于String.JoinAggregate

例如:

IEnumerable<string> strings;
string joinedString = strings.Aggregate((total,next) => total + ", " + next);

如果给出TableRows的IE,则代码将类似。


7
投票

在.NET 3.5中,您可以使用此扩展方法:

public static string Join<TItem>(this IEnumerable<TItem> enumerable, string separator)
{
   return string.Join(separator, enumerable.Select(x => x.ToString()).ToArray());
}

或者在.NET 4中

public static string Join<TItem>(this IEnumerable<TItem> enumerable, string separator)
{
   return string.Join(separator, enumerable);
}

但问题是在每个元素之后需要一个分隔符,包括这个(3.5版本)可用的最后一个元素: -

public static string AddDelimiterAfter<TItem>(this IEnumerable<TItem> enumerable, string delimiter)
{
   return string.Join("", enumerable.Select(x => x.ToString() + separator).ToArray());
}

您也可以使用.Aggregate在没有扩展方法的情况下执行此操作。


1
投票

如果我找不到适合我需要的方法,我会创建自己的方法。扩展方法非常好,因为它们可以让你扩展这样的东西。不太了解asp:table,但这里至少是一个扩展方法,你可以调整到任何:p

public static class TableRowExtensions
{
    public string JoinRows(this IEnumerable<TableRow> rows, string separator)
    {
        // do what you gotta do
    }
}

1
投票

您正在寻找的是Intersperse功能。有关此类函数的LINQ实现,请参阅this question


顺便说一句,String.Join的另一个可能的类比是Intercalate函数,这实际上是我正在寻找的:

public static IEnumerable<T> Intercalate<T>(this IEnumerable<IEnumerable<T>> source,
                                            IEnumerable<T> separator) {
    if (source == null) throw new ArgumentNullException("source");
    if (separator == null) throw new ArgumentNullException("separator");
    return source.Intersperse(separator)
        .Aggregate(Enumerable.Empty<T>(), Enumerable.Concat);
}

1
投票

我发现我经常使用这种扩展方法。

幸运的是,它可能是incorporated into C#

public static class Extensions
{
    public static string ToString(this IEnumerable<string> list, string separator)
    {
        string result = string.Join(separator, list);
        return result;
    }
}

用法:

var people = new[]
{
    new { Firstname = "Bruce", Surname = "Bogtrotter" },
    new { Firstname = "Terry", Surname = "Fields" },
    new { Firstname = "Barry", Surname = "Wordsworth"}
};

var guestList = people
                    .OrderBy(p => p.Firstname)
                    .ThenBy(p => p.Surname)
                    .Select(p => $"{p.Firstname} {p.Surname}")
                    .ToString(Environment.NewLine);

0
投票

没有内置方法可以做到这一点,你应该自己动手。


0
投票

如果你经常要做这种事情,那么建立你自己的扩展方法是值得的。下面的实现允许你做相当于string.Join(", ", arrayOfStrings)的数组,其中arrayOfStrings可以是IEnumerable<T>,而separator可以是任何对象。它允许你做这样的事情:

var names = new [] { "Fred", "Barney", "Wilma", "Betty" };
var list = names
    .Where(n => n.Contains("e"))
    .Join(", ");

我喜欢的两件事是:

  1. 它在LINQ上下文中非常易读。
  2. 它相当高效,因为它使用StringBuilder并避免两次计算枚举。
public static string Join<TItem,TSep>(
    this IEnumerable<TItem> enuml,
    TSep                    separator)
{
    if (null == enuml) return string.Empty;

    var sb = new StringBuilder();

    using (var enumr = enuml.GetEnumerator())
    {
        if (null != enumr && enumr.MoveNext())
        {
            sb.Append(enumr.Current);
            while (enumr.MoveNext())
            {
                sb.Append(separator).Append(enumr.Current);
            }
        }
    }

    return sb.ToString();
}
© www.soinside.com 2019 - 2024. All rights reserved.