В vb.net Как преобразовать список объектов в другом списке объектов в строку csv. Я пробовал ниже, не сработало

String.Join(",", Person.Cars.Select(Function(d) d.Colors.Select(Function(o) o.colorid.ToString)))

Вывод должен иметь цветной идентификатор в строке csv, например: «101,102,103».

Если я попробую использовать идентификаторы автомобилей, которые работают должным образом

String.Join(",", Person.Cars.Select(Function(d) d.carid.ToString)) 

Вывод "2001,2002,2003"

Вот как строятся данные

   Dim objPerson As New Person
    With objPerson 
    .Cars = new Cars (1) {}
    .Cars(0) = new Cars
    .Cars(1) = new Cars

    With Cars(0)
    .CarId = "2001"

    .Colors = new Colors(1){}
    .Colors(0) = new Colors
    .Colors(1) = new Colors

    With .Colors(0)
    .Colorid = "101"
    End With

    With .Colors(1)
    .Colorid = "102"
    End With

    End With



    With Cars(1)
    .CarId = "2002"

    .Colors = new Colors(1){}
    .Colors(0) = new Colors
    .Colors(1) = new Colors

    With .Colors(0)
    .Colorid = "103"
    End With

    With .Colors(1)
    .Colorid = "104"
    End With

    End With


    End With
End With
-1
Gauls 17 Фев 2015 в 15:28

2 ответа

Лучший ответ

Используйте SelectMany вместо Select, чтобы сгладить результат, передаваемый в String.Join:

String.Join(",", Person.Cars.SelectMany(Function(d) d.Colors.Select(Function(o) o.colorid.ToString)))

В ответ на ваш комментарий:

Кажется, вы ищете что-то вроде

String.Join(",", Person.Cars.Select(Function(d) String.Join("", d.Colors.Select(Function(o) o.colorid.ToString))))
0
sloth 17 Фев 2015 в 13:26

LINQ может быть очень полезным инструментом. Это не значит, что он позволяет вам делать то, что вы не могли бы сделать другими способами. Просто он позволяет вам делать некоторые вещи намного проще, чище и удобочитаемее. Это не пример одной из таких ситуаций. В этом случае использование LINQ может не только сбить с толку других, но и сбить с толку вас. Я полностью за то, чтобы использовать LINQ в тех местах, где он упрощает чтение кода, но, поскольку это единственная реальная выгода, я не вижу причин использовать его там, где это затрудняет чтение кода.

Хорошо, теперь, когда я сошел с ума, позвольте мне объяснить вашу проблему. У вас есть два вызова LINQ, вложенных друг в друга. Внутренний возвращает список идентификаторов цветов для автомобиля. Внешний вызывает внутренний один раз для каждой машины в списке. Это означает, что в конечном итоге у вас нет единого списка идентификаторов цветов для всех автомобилей. Скорее, у вас есть двумерный список, в котором, по сути, есть одна строка для каждого автомобиля и один столбец для каждого идентификатора цвета. Вам нужно свернуть его в одномерный список.

Вы можете сделать это в LINQ примерно так:

String.Join(",", Person.Cars.Select(Function(d) String.Join(",", d.Colors.Select(Function(o) o.colorid.ToString))))

Или используя SelectMany, как рекомендует sloth , но я бы сказал, что вы расширяете границы удобочитаемости и должны серьезно подумать о том, чтобы попытаться снизить свой коэффициент сообразительности и просто пойти с более простым и понятным циклом For. Если это заставляет меня казаться старомодным, пусть будет так. Например, я бы сказал, что что-то вроде этого вызовет гораздо меньше царапин на голове:

 Private Function GetAllColorIds(cars As IEnumerable(Of Car)) As IEnumerable(Of Integer)
     Dim result As New List(Of Integer)()
     For Each i As Car In cars
         result.AddRange(i.Colors.Select(Function(x) x.colorid.ToString())
     Next
     Return result
 End Function

 ' ...

 Dim csv As String = String.Join(",", GetAllColorIds(Person.Cars))
1
Steven Doggart 17 Фев 2015 в 13:24