Как я могу построить строку из коллекции с Linq? - PullRequest
3 голосов
/ 09 октября 2009

Я создаю содержимое плоских файлов из коллекций строк.

Пример коллекции: A, B, C, D, E и т. Д.

Я хочу иметь возможность выводить эти значения в строку с переводами строки одним махом с Linq, если это возможно.

Пример вывода:

A

B

C

D

E

и т.д.

Вот код VB.NET, который выполняет работу в данный момент:

For Each fieldValue As String In field.Values
   fileContent.Append(fieldValue + Environment.NewLine)
Next

Я пробовал несколько способов заставить Линка выполнять свою работу, но не смог найти правильную комбинацию. Мысли?

Ответы [ 8 ]

11 голосов
/ 09 октября 2009

Вы пробовали простое соединение? ..

если field.Values ​​уже является массивом строк, тогда это должно работать нормально .. в противном случае вы можете использовать LINQ .ToArray() для преобразования коллекции в массив.

string joined = string.Join(Environment.NewLine, field.Values);

VB

Dim joined As String = String.Join(Environment.NewLine, field.Values)

Просто подумал, что я бы добавил, если бы вы действительно, действительно хотели сделать это с LINQ, Aggregrate сработал бы, хотя я бы не очень рекомендовал это для ваших нужд.

field.Values.Aggregate(string.Empty, (s1, s2) => s1 += Environment.NewLine + s2);
2 голосов
/ 09 октября 2009

Я создал эти методы расширения, которые можно использовать для объединения любого количества элементов в коллекции. Это может быть немного излишним для вашего примера, но если вам нужно объединить элементы, которые являются объектами, а не строками, это может отлично работать.

Использование:

fileContent = field.Values.Contatenate(Environment.NewLine);

Расширения:

public static class EnumerableExtensions
{
    public static string Concatenate<T>(this IEnumerable<T> source, string seperator)
    {
        return Concatenate(source, i => i.ToString(), seperator);
    }

    public static string Concatenate<T>(this IEnumerable<T> source, Func<T, string> selector, string seperator)
    {
        var builder = new StringBuilder();
        foreach (var item in source)
        {
            if (builder.Length > 0)
                builder.Append(seperator);

            builder.Append(selector(item));
        }
        return builder.ToString();
    }

    public static string ToCsv<T>(this IEnumerable<T> source)
    {
        return Concatenate(source, i => i.ToString(), ",");
    }

    public static string ToCsv<T>(this IEnumerable<T> source, Func<T, string> selector)
    {
        return Concatenate(source, selector, ",");
    }
}
1 голос
/ 22 октября 2009

Обратите внимание, что .NET 4.0 включает новый String.Concat () статический метод, который принимает IEnumerable<T> и вызывает ToString для каждого объекта в списке. Должно пригодиться!

1 голос
/ 09 октября 2009

Вы можете использовать StringBuilder в методе расширения Aggregate:

Dim fileContent As String = _
   field.Values.Aggregate( _
      New StringBuilder(), _
      Function(b, i) b.AppendLine(i) _
   ).ToString()
1 голос
/ 09 октября 2009

Вы можете использовать метод Aggregate, чтобы добраться до него, но он не будет столь же эффективным, как цикл foreach, который добавляется к файлу или StringBuilder.

Я полагаю, что ваша основная проблема в том, что Linq правильно использует для возврата результатов. Разработчики не собирались использовать оператор Linq для изменения объектов, через которые он проходит. Это, вероятно, объясняет общие трудности, с которыми вы столкнулись при выполнении этого задания.

Не забывайте, что foreach - это правильный способ использовать результаты Linq!

0 голосов
/ 09 октября 2009

Создать метод расширения -

<Extension()> _
Public Function Flatten(ByVal stringList As IList(Of String), ByVal delimiter As String) As String
        Dim strB As New StringBuilder

        For Each Str As String In stringList
            If strB.ToString.Length > 0 Then
                strB.Append(delimiter)
            End If
            strB.Append(Str)
        Next
        Return strB.ToString
    End Function

Если у вас есть это, вы можете просто делать то, что вы хотите, как это -

Dim letters as New List(Of String)
'do your loading of the list

Dim formattedString As String = letters.Flatten(Environment.NewLine)
0 голосов
/ 09 октября 2009

Возможно, вы захотите использовать IEnumerable.Aggregate .

Ваш код будет выглядеть примерно так:

Dim fileContentString As String = _
        field.Values.Aggregate(Function(ByVal JoinedValues, ByVal DiscreteValue) 
            JoinedValues & Environment.NewLine & DiscreteValue)

Отказ от ответственности - только потому, что вы МОЖЕТЕ использовать Linq,не означает, что это правильный инструмент для этой работы.Как отмечали другие, цикл ForEach был бы более эффективным.

0 голосов
/ 09 октября 2009

Если Values является списком, вы можете сделать это ...

field.Values.ForEach(o=>fileContent.Append(o + Environment.NewLine));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...