0

Fellow coders,

I'm looking for a simpel and fast solution to retrieve some object values in a List(of Object) an then combine those values to a two dimensional array.

Let me talk in code to explain:

Public Class MyMainClass
   Dim lstObjects as new list(of TestObject)

   Sub New()
      lstObjects.Add(new TestObject With {.IndexPos = 2,
                                          .Value1 = 4578,
                                          .Value2 = 9876234)

      lstObjects.Add(new TestObject With {.IndexPos = 8,
                                          .Value1 = 45232378,
                                          .Value2 = 98761111234)

      RetrieveValues(New Integer() {1, 4, 8}
   End Sub


   Function RetrieveValues(SearchValues()) as integer (,)

     Dim y As IEnumerable(Of TestObject) = Sources.Where(Function(a) a.IndexPos .Equals(SearchValues))

    'Then do something here to convert Value1 and Value 2 of the object to a two dimensional array

   End function
End Class


Public Class TestObject
   Public IndexPos As Integer
   Public Value1 As Integer
   Public Value2 As Integer
End Class

The code is an example and not tested (written just here in this editor). The TestObject doesn't contain many values here, but in the real applications it has many properties. Hopefully you understand what i'm trying to achieve and could help me out on this. I've spend several hours on google to find a solution...

Gforse
  • 323
  • 3
  • 20

2 Answers2

0

Handling multidimensional arrays is not so easy with Linq. See a bigger discussion on this here.

In this case, I'd go for good old VB.NET and iterate through the items you already got in your variable y - however, I'd put that in a list before accessing it multiple times.

Dim items = y.ToList()
Dim result(items.Count, 2) as Integer ' god I hate that syntax

For itemIndex As Integer = 0 To items.Count - 1
    result(itemIndex, 0) = items(itemIndex).Value1
    result(itemIndex, 1) = items(itemIndex).Value2
Next
Waescher
  • 5,361
  • 3
  • 34
  • 51
  • Two people one mind ;-) I had this exact code. Which can work, except for the fact that the first LINQ Query doesn't give me any result. I'm still stuk on how to pass an search Array into a LINQ query and get the matching results... – Gforse Jun 16 '17 at 08:01
  • This could be because you compare the `IndexPos` with all the search values. These are never the same (`Int32` vs. `Array-of-Int32)`). I think what you want to have is a kind of Contains-search. To be able to do that, put your `SearchValues` to a list like this: `Dim searchList As List(Of Int32) = SearchValues.ToList()`. Then you can check with Contains like this: `Sources.Where(Function(a) searchList.Contains(a.IndexPos))` – Waescher Jun 16 '17 at 08:04
  • Great, that was exactly what i was looking for. I ended up using this: `Dim y As IEnumerable(Of TestObject) = lstObjects.Where(Function(a) SearchValues.Contains(a.IndexPos)) intResultSize = y.Count - 1 ReDim intInputMeters(intResultSize, 1) For i As Integer = 0 To intResultSize result(i, 0) = y(i).Value1 result(i, 1) = y(i).Value2 Next Return result` – Gforse Jun 16 '17 at 08:35
  • Hard to read but looks good. Is your question answered with that? – Waescher Jun 16 '17 at 08:36
  • Yes, i will post it as the answer. (unless someone has a faster/cleaner solution?) Thanks! :-) – Gforse Jun 16 '17 at 08:37
  • Did some further testing and with large collection is rather slowish... Is it possible to create a Parrallel for each of the .where function? – Gforse Jun 16 '17 at 10:50
  • Get rid of the `ReDim` and make sure the sizing of the array is final before you do the work. That's expensive. – Waescher Jun 16 '17 at 10:55
  • About the performance of the lambda: As in my code sample above, make sure to have a `List(Of )` instead of an Array when calling `Contains()`. – Waescher Jun 16 '17 at 11:19
0

After all the good advice of Waescher i finnaly made this, wich works fast en exactly how i wanted it.

PS. Als you can see i compare the array in the LINQ, this is because i couldn't change is to a List of T, as Waescher earlier mentioned.

''' <summary>
''' Stores all the input meter values
''' </summary>
Private intInputMeters(,) As Integer

Sub SetArraySize(InputMeters() As Integer)
        'Redim the return integer array's for the meter values
        ReDim intInputMeters(InputMeters.Length, 1)
End sub


Public Function GetInputMeters() As Integer(,)

    'Search for the machting sources and return the once we found.
    Dim y As IEnumerable(Of Source) = Sources.Where(Function(a) intInputMeterRequest.Contains(a.ChannelNumber)).AsParallel

    'Now pass the values to the array
    For i As Integer = 0 To y.Count - 1
        intInputMeters(i, 0) = y(i).MeterValueLeft
        intInputMeters(i, 1) = y(i).MeterValueRight
    Next

    'Return the new filled array to the user
    Return intInputMeters
End Function
Gforse
  • 323
  • 3
  • 20
  • Would using a `Dictionary` work for you? It looks like you're trying to do a dictionary lookup on a `List`, which will necessarily be less efficient---lookup in a `List` is linear time, lookup in a `Dictionary` is constant time providing it's hashed reasonably well. – Craig Jun 16 '17 at 17:43
  • Hey Craig, Unfortunately not because the object has a lot more values. For the example is just exposed three of them. Thanks for thinking with me. – Gforse Jun 20 '17 at 13:34