3

I am trying to implement Map in VB.NET with the functionality described in this answer.

It should take an IEnumerable(Of TIn) and a Function(Of TIn, TOut), execute the function over every element, and return a new IEnumerable(Of TOut).

I know VB.NET is not a true functional language. I have business requirements, but would still like to use some functional tidbits, especially in conjunction with LINQ.

A similar question is asked here, but the question and answer are actually about implementing Each.

Community
  • 1
  • 1
Z_AHK
  • 71
  • 1
  • 10
  • That _Map_ you want is already there it's the Linq [Select](https://msdn.microsoft.com/en-us/library/bb548891%28v=vs.110%29.aspx) method – Sehnsucht Jun 23 '15 at 18:54
  • Aw, dang. I searched for quite a while and couldn't find anything for a `Map` function in VB.NET when I should have just remembered `Select`. Thank you. At least I learned a lot about `Generics`. – Z_AHK Jun 23 '15 at 19:09

2 Answers2

2

Thanks to @Sehnsucht for pointing out that there already is a Map function in LINQ that is called Select.

Here is my original answer that is definitely not as good as what the smart people designing LINQ created:

Here is a an extension method that can be placed in a Module in the root namespace:

Module Extensions
    <System.Runtime.CompilerServices.Extension> _
    Public Function Map(Of TIn, TOut)(ByVal a As IEnumerable(Of TIn), ByVal f As Func(Of TIn, TOut)) As IList(Of TOut)
        Dim l As New List(Of TOut)
        For Each i As TIn In a
            Dim x = f(i)
            l.Add(x)
        Next
        Return l
    End Function
End Module

It can be called like:

Sub Main()
    Dim Test As New List(Of Double) From {-10000000, -1, 1, 1000000}
    Dim Result1 = Test.Map(Function(x) x.ToString("F2"))
    'Result1 is of type IList(Of String)
    Dim Result2 = Test.Map(AddressOf IsPositive)
    'Result2 is of type IList(Of Boolean)
    Dim Result3 = Map(Test, Function(y) y + 1)
    'Result3 is of type IList(Of Double)
End Sub

Private Function IsPositive(d As Double) As Boolean
    If d > 0 then
        Return True
    Else
        Return False
    End If
End Function

I return an IList(Of TOut) because it is more useful for my purposes (and, well, it's returning a list!). It could return an IEnumerable(Of TOut) by changing the return line to Return l.AsEnumerable(). It accepts an IEnumerable(Of TIn) instead of an IList(Of TIn) so it can accepts a wider range of inputs.

I'm open to anybody suggesting performance improvements.

Community
  • 1
  • 1
Z_AHK
  • 71
  • 1
  • 10
  • if you really want to reimplement it yourself ; use an [iterator block](https://msdn.microsoft.com/en-us/library/hh156569.aspx) – Sehnsucht Jun 23 '15 at 19:06
  • Thanks. I was thinking about that, but I don't know enough to fully understand how it would work if I called `Map` on a LINQ-to-SQL query. – Z_AHK Jun 23 '15 at 19:12
  • I'm not sure if your auto-answer is useful at all... When someone told you there's a `Select` method to map objects I would have deleted the question itself ;P – Matías Fidemraizer Jun 23 '15 at 20:14
  • @MatíasFidemraizer I disagree because I spent a lot of time looking up variations of `Map` for VB.NET and didn't find anything so then I spent time implementing my own. I think the question should stay so if anyone else is coming from a different language where it is called `Map` and searches like me without knowing the vocabulary, they won't waste their time. – Z_AHK Jun 23 '15 at 20:56
  • @Z_AHK You spent a lot of time, but for example, I would code your map function in less than a minute... I mean, when you know how iterators work, it seems like an answer like yours isn't useful, because it's more useful to use LINQ Select extension method directly....... It would be useful if your Q&A would be "how is LINQ Select implemented?"... – Matías Fidemraizer Jun 24 '15 at 06:35
2

super simple

   Public Function map(equation As Func(Of Object, Object))

    For i = 0 To rows - 1
        For j = 0 To cols - 1
            Dim val = data(i, j)
            data(i, j) = equation(val)
        Next
    Next
End Function

and to use it

 m.map(Function(x) 3 > x)
 m.map(Address Sigmoid)
Shynka
  • 21
  • 3