Creating a String from a Collection of Objects
I have a question. I have a class of Cars
that I need to display in a simpli-ish string if they will be sold or not base on their number.
So like this:
Public Class Car
Property Index As Integer
Property Sell As Boolean
End Class
Public Class Cars
Property Vehicles As New List(Of Car) From {
{New Car With {.Index = 1, .Sell = True}},
{New Car With {.Index = 2, .Sell = False}},
{New Car With {.Index = 3, .Sell = True}},
{New Car With {.Index = 4, .Sell = True}},
{New Car With {.Index = 5, .Sell = True}},
{New Car With {.Index = 6, .Sell = False}},
{New Car With {.Index = 7, .Sell = True}},
{New Car With {.Index = 8, .Sell = True}},
{New Car With {.Index = 9, .Sell = False}},
{开发者_开发问答New Car With {.Index = 10, .Sell = False}},
{New Car With {.Index = 11, .Sell = True}}}
End Class
I'd like to display a simple string like this:
Cars to be sold: 1, 3-5, 7-8, 11, which is based of the .Sell
value.
Is there some kind of heuristic to create this kind of string in .NET or is it just a bunch of for/each and if/then and redimming of arrays?
LINQ would definitely simplify the solution. Without LINQ you could use a StringBuilder
and iterate over the list while comparing neighboring items and build up the string. That would be more ideal rather than redimming arrays and such.
Here's a LINQ solution:
Dim query = vehicles.Where(Function(c) c.Sell) _
.OrderBy(Function(c) c.Index) _
.Select(Function(c, i) New With { .Car = c, .Diff = c.Index - vehicles(i).Index }) _
.GroupBy(Function(item) item.Diff) _
.Select(Function(item) item.First().Car.Index.ToString() &
If(item.Count() > 1, "-" & item.Last().Car.Index.ToString(), ""))
Console.WriteLine("Cars to be sold: " & String.Join(", ", query.ToArray()))
With .NET 4 you can drop the ToArray()
call since String.Join
has an overload that accepts an IEnumerable<T>
.
The code filters out cars with a Sell
value of True
. It is important for the list to be in order of Car.Index
for this to work properly, hence the OrderBy
. The logic behind determining consecutive items is to compare neighboring items and group them based on their index difference. If there's a difference of 1 then they are neighbors. So the second Select
projects into an anonymous type that stores the Car
and the Diff
based on the current index minus the previous car's index. The GroupBy
groups all the differences together. The last Select
builds the range. If the Count
is greater than 1 we put a dash between the first and last group items. Otherwise one item exists and we select it as it is. Finally we use String.Join
to return the list of values separated by commas.
I would do this:
Dim list_sold = Vehicles.Where(Function(x As Car) x.Sell = True)
Dim list_index = list_sold.Select(Function(x As Car) x.Index.ToString())
Console.WriteLine("Cars to be sold: {0}", String.Join(", ", list_index))
精彩评论