Show MsgBox() data from two arrays in a loop - vb.net

I'm trying to write code to show data from two arrays via a MsgBox(). I have the code below, but of course it doesn't work:
Dim numbers() As Integer = {1, 4, 7}
Dim letters() As String = {"a", "b", "c"}
' Iterate through the list by using nested loops.
For Each number As Integer In numbers and For Each letter As String In letters
MsgBox(number.ToString & letter & " ")
Next
What do I need to do to get output that looks like this? :
1a
4b
7c

You need a For loop that uses an index rather than a For Each loop:
Dim numbers() As Integer = {1, 4, 7}
Dim letters() As String = {"a", "b", "c"}
For i As Integer = 0 To numbers.Length - 1
MsgBox(numbers(i) & letters(i))
Next
You can also use the Zip() linq operator:
For Each output As String In numbers.Zip(letters, Function(n, l) n & l)
MsgBox(output)
Next

You may benefit from something like a dictionary. Not sure what you're trying to accomplish combining 2 arrays arbitrarily but something like this may be better:
Dim Dict As New Dictionary(Of Integer, String) From {{1, "a"}, {4, "b"}, {7, "c"}}
For Each Item In Dict
MsgBox(Item.Key & Item.Value)
Next
That would allow you to lookup items based on the ID (integer) with Linq such as:
Dict.Where(Function(x) x.Key = 1).SingleOrDefault and grab the key/value pair.

Related

Find the indices of matching elements of two lists

vb.NET
I have two lists (listA and listB) and want to return a new list (listC) containing listB’s indices of the matching elements when compared to listA.
So, let’s say: listA = 3,4,5 and listB = 1,2,3,4,5,6,7. I’d like listC to return 2,3,4 because those are the indices of the matches in listB.
The following code will return the matching values of listA and listB in listC.
Dim commonlist = listA.Intersect(listB).ToList()
For each common As String In commonlist
listC.Add(common)
Console.WriteLine(common)
Next common
How can I return the indices to listC, or a new listD for that matter?
Dim listC = listA.Select(Function(itemA) listB.IndexOf(itemA)).ToList()
In case you're not familiar with LINQ, the Select method takes a function to map items in a list to a new list. It is completely up to you what that mapping function does. It's commonly getting a single property value from the items but, in your case, it's getting the index of the items in the other list.
Select returns an IEnumerable(Of T) and that's all you need if all you plan to do is run a For Each loop over it, but you can call ToList to create a List(Of T) if that's what you want.
EDIT:
I think that I may have misinterpreted the question slightly. I'll leave my original answer as what I have done is basically the listD requested in the question but I'll add information about getting the items and the indexes.
Here is one option:
Dim listA As New List(Of Integer) From {1, 2, 3, 9}
Dim listB As New List(Of Integer) From {1, 2, 3, 4, 5, 6}
Dim listC = listA.Select(Function(a) Tuple.Create(a, listB.IndexOf(a))).
Where(Function(ta) ta.Item2 <> -1).
ToList()
For Each ta In listC
Console.WriteLine("Value: {0}; Index: {1}", ta.Item1, ta.Item2)
Next
That code will create a list of Tuples where each one contains a value from listA and the index of that value in listB. Those values not in both lists are excluded.
If you want something a bit nicer than a Tuple then you can create a Dictionary:
Dim listA As New List(Of Integer) From {1, 2, 3, 9}
Dim listB As New List(Of Integer) From {1, 2, 3, 4, 5, 6}
Dim dictionaryC = listA.Select(Function(a) Tuple.Create(a, listB.IndexOf(a))).
Where(Function(ta) ta.Item2 <> -1).
ToDictionary(Function(ta) ta.Item1,
Function(ta) ta.Item2)
For Each key In dictionaryC.Keys
Console.WriteLine("Value: {0}; Index: {1}", key, dictionaryC(key))
Next
If you specifically want two separate lists then you can do this:
Dim listA As New List(Of Integer) From {1, 2, 3, 9}
Dim listB As New List(Of Integer) From {1, 2, 3, 4, 5, 6}
Dim listC = listA.Intersect(listB).ToList()
Dim listD = listC.Select(Function(c) listB.IndexOf(c)).ToList()
For i = 0 To listC.Count - 1
Console.WriteLine("Value: {0}; Index: {1}", listC(i), listD(i))
Next

Linq How to combine List Items to other List items

I have multiple list of string with some items
want to combine every items together like below
Dim _rsltitm = Nothing
For Each _itm1 In _lst1
For Each _itm2 In _lst2
For Each _itm3 In _lst3
_rsltitm &= vbNewLine & _itm1 + _itm2 + _itm3
Next
Next
Next
above code is working fine but i have more than 8 lists or sometimes 11
so i need linq to combine multiple list of string items together
i am trying like this but i could not
Dim _rslt = From itm In _lst1 Select (Function(x) From itm2 In _lst2 Select (Function(d) x & d))
I just tested this code and it seems to do what you want:
Dim list1 As New List(Of String) From {"1", "2", "3"}
Dim list2 As New List(Of String) From {"A", "B", "C"}
Dim list3 As New List(Of String) From {"7", "8", "9"}
Dim list4 As New List(Of String) From {"X", "Y", "Z"}
Dim lists = {list1, list2, list3, list4}
Dim result = lists.Aggregate(Function(current, list)
Dim combinedList As New List(Of String)
For Each prefix In current
combinedList.AddRange(From suffix In list Select prefix & suffix)
Next
Return combinedList
End Function)
You just add all your lists to that lists array and result should end up containing the desired result.
I feel like that Lambda body should be able to be LINQified a bit more but my initial attempts didn't work so I gave up quickly. If you want to put some more time into it, you're welcome to.
EDIT:
Here's that in a function:
Private Function CombineLists(ParamArray lists As List(Of String)()) As List(Of String)
Return lists.Aggregate(Function(current, list)
Dim combinedList As New List(Of String)
For Each prefix In current
combinedList.AddRange(From suffix In list Select prefix & suffix)
Next
Return combinedList
End Function)
End Function
In my example, I could either call that like so:
Dim result = CombineLists(list1, list2, list3, list4)
or like so:
Dim lists = {list1, list2, list3, list4}
Dim result = CombineLists(lists)

VB.Net equivalent of Javascript's .Map function

Given an array of strings, say: Dim array1 As String() = {"1", "2", "3"} what is the best way to copy that array and perform an action on each element?
In other words, what is the best way to copy that array to come up with: array2 as integer() = {1, 2, 3}
For example, something similar to JavaScript's .Map function:
var numbers = [4, 9, 16, 25];
function myFunction() {
x = document.getElementById("demo")
x.innerHTML = numbers.map(Math.sqrt);
}
// Result: 2, 3, 4, 5
If it isn't possible in one line - as I suspect it isn't - what is your quickest alternative? Thanks!
If you don't want to use any LINQ extension methods, but you are okay with using lambda expressions, you can still do it in one line using Array.ConvertAll:
Dim input() As String = {"1", "2", "3"}
Dim output() As Integer = Array.ConvertAll(input, Function(x) Integer.Parse(x))
However, it does beg the question: why not just use LINQ, at that point, since it's effectively the same thing:
Dim input() As String = {"1", "2", "3"}
Dim output() As Integer = input.Select(Function(x) Integer.Parse(x)).ToArray()
The classic imperative way to do this in VB, without using LINQ or lambdas, would be a for-loop:
Dim input() As String = {"1", "2", "3"}
Dim output(LBound(input) To UBound(input)) As Integer
For i As Integer = LBound(input) To UBound(input)
output(i) = Integer.Parse(input(i))
Next
I would like to add that, similar to JavaScript, .NET's map equivalent Select also supports method groups as well as lambdas.
Here's an example using a lambda:
Dim output = input.Select(Function(x) SomeMethod(x)).ToArray()
Here's an example using a method group. Since parenthesis on method invocations are optional in VB.NET, the additional AddressOf keyword is required:
Dim output = input.Select(AddressOf SomeMethod).ToArray()
For completeness, here's an example using the LINQ query syntax, which is just syntactic sugar for the first example:
Dim output = (From x In input Select SomeMethod(x)).ToArray()
If you don't want to use LINQ here is the classic way, a loop:
Dim numbers = {4, 9, 16, 25}
For i As Int32 = 0 To numbers.Length - 1
numbers(i) = CInt(Math.Sqrt(numbers(i)))
Next

How to add a character to the beginging of each string in a list of strings

I have a simple list of strings and what i need to do is to add "#" to the beginning of each item and join the list to get something like: "#item1, #item2,...."
my code so far:
Dim list As New List(Of String)({"item1", "item2", "item3", "item4"})
' create a copy of list to prevent altering it
Dim listCopy As List(Of String) = list
For i As Integer = 0 To listCopy.Count - 1
list(i) = "#" & listCopy(i)
Next
Dim result As String = String.Join(", ", list.ToArray())
While this does the job but i feel that it's too much code for a simple function, the same thing can be done in python or javascript much easier like:
python:
copyList = [("#" + x) for x in list]
javascript:
copylist = list.map(function(x){return '#' + x})
Is there a similar function in vb.net?
Yes, you can use the LINQ Select method to achieve this:
Dim list As New List(Of String)({"item1", "item2", "item3", "item4"})
dim list1 = list.Select(function (i) "#" + i)
for each item in list1
Console.WriteLine(item)
next item
And the output is:
#item1
#item2
#item3
#item4
The result is an IEnumerable (Of String) object. If you want again a List (Of String) than use the ToList() extension method:
dim list1 = list.Select(function (i) "#" + i).ToList()
Use LINQ:
Dim result = (From s In list Select "#" & s)

Convert integer array to string array

whats the easiest way to convert an array of integers into string form? I'm trying to copy the whole array of integers into strings.
{1, 2, 3}
to
{"1", "2", "3"}
The easiest method would be to use the Select extension method which is provided by LINQ:
Dim intArray() As Integer = {1, 2, 3}
Dim strArray() As String = intArray.Select(Function(x) x.ToString()).ToArray()
If you don't want to, or cannot use LINQ, you can use the Array.ConvertAll method, which is almost as easy:
Dim strArray() As String = Array.ConvertAll(Of Integer, String)(intArray, Function(x) x.ToString())
EDIT
Based on your comments, below, it looks like you need to convert from an ArrayList of integers to an ArrayList of strings. In that case, you could do it like this:
Dim intArray As New ArrayList({1, 2, 3})
Dim strArray As New ArrayList(intArray.ToArray().Select(Function(x) x.ToString()).ToArray())
Although, at that point, it's starting to get a bit messier. It's probably easier to just do a standard loop, like this:
Dim myArray As New ArrayList({1, 2, 3})
For i As Integer = myArray.Count - 1 To 0 Step -1
myArray(i) = myArray(i).ToString()
Next
For what it's worth, though, unless you are still on a really old version of the .NET Framework, you really ought to be using the List(Of T) class rather than the ArrayList class, in most cases.