from list to string with formatting - vb.net

i have a function getSelectedNumbers that take as input 3 list of number. after a manipulation i need to obtain a string in the format
"[1_3,10,20,30,500],[1_1,2],[]"
if the list is empty i need to have in the string the "[]" char
i wrote the below function but i need to manage the empty case.
Based on comment of Anu6is :
i was able to rewrite my code as below
'''vb
Public Function getSelectedNumbers() As String
Dim selectedNumbers1 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel1.Find(".//div[#class='selected']")
Dim selectedNumbers2 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel2.Find(".//div[#class='selected']")
Dim selectedNumbers3 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel3.Find(".//div[#class='selected']")
Dim list1 As New List(Of String)
Dim list2 As New List(Of String)
Dim list3 As New List(Of String)
For i As Integer = 0 To selectedNumbers1.Count -1
list1.Add(selectedNumbers1(i).GetAttributeValue("innerText").ToString)
Next i
For i As Integer = 0 To selectedNumbers2.Count -1
list2.Add(selectedNumbers2(i).GetAttributeValue("innerText").ToString)
Next i
For i As Integer = 0 To selectedNumbers3.Count -1
list3.Add(selectedNumbers3(i).GetAttributeValue("innerText").ToString)
Next i
'Create List of List
Dim selectedNumbersList As New List(Of List(Of String)) From {list1, list2, list3}
Dim builder As New StringBuilder 'Used to build the output
'Convert all the list in the correct string format using the join
For Each listX As List(Of String) In selectedNumbersList
builder.Append("[1_").Append(String.Join(",", listX)).Append("],") 'String.Join() give you a comma delmited string
Next
'Remove the last, and the [1_] that are not needed
Dim strSelectedNunmber As String = builder.ToString().TrimEnd(","c)
strSelectedNunmber = strSelectedNunmber.ToString().Replace("[1_]","[]")
Return str
End Function
'''
now my question is there is a better way to generate the list1 list2 list3 ?

This is assuming that Element is simply an Integer
Public Function getSelectedNumbers() As String
Dim selectedNumbers1 As New List(Of Integer) From {20, 30, 500, 10, 3} 'Unordered list
Dim selectedNumbers2 As New List(Of Integer) From {1, 2, 500} 'Ordered list
Dim selectedNumbers3 As New List(Of Integer) 'empty list
Dim selectedNumbersList As New List(Of List(Of Integer)) From {selectedNumbers1, selectedNumbers2, selectedNumbers3}
Dim builder As New StringBuilder 'Used to build the output
For Each list In selectedNumbersList
list.Sort() 'Sort your list
builder.Append("[").Append(String.Join(",", list)).Append("],") 'String.Join() give you a comma delmited string
Next
Return builder.ToString.TrimEnd(","c) 'Remove the final comma (,) and return the formatted string
End Function
[3,10,20,30,500],[1,2,500],[]

Does this work for you?
Dim selectedNumbers1 As New List(Of Integer) From {20, 30, 500, 10, 3}
Dim selectedNumbers2 As New List(Of Integer) From {1, 2, 500}
Dim selectedNumbers3 As New List(Of Integer)
'either make 3 loops or 1, but you have to make a list of lists first
Dim selectedNumbersList As New List(Of List(Of Integer)) From {selectedNumbers1, selectedNumbers2, selectedNumbers3}
For Each listX In selectedNumbersList
listX.Sort()
Dim ReturnString As String = "["
If listX.Count > 0 Then
For Each itemvalue In listX
ReturnString &= itemvalue & ","
Next
ReturnString = ReturnString.Remove(ReturnString.Length - 1)
End If
ReturnString &= "]"
Debug.Print(ReturnString)
Next
'[3,10,20,30,500]
'[1,2,500]
'[]

Related

repetition time of adding data list

resembles a python code like this
while listCompanion :
in vb net I tried to use the code For Each kvp In listCompanion but failed
Dim listCompanion As New Dictionary(Of String, String()) From {"dessy", New String() {"age: 21", "gender: girl"}}
Dim kvp As KeyValuePair(Of String, String())
ListBox1.Items.Clear()
For Each kvp In listCompanion
Dim member As String = String.Format("{0} = {1} - {2}", kvp.Key, kvp.Value(0), kvp.Value(1))
ListBox1.Items.Add(member) 'I want every additions will enter the listbox
If listCompanion.Count < 2 Then 'Error here
listCompanion.Add({"jony", New String() {"age: 25", "gender: boy"}})
End If
next
when you want to add a data list, the For Each actually not working again
I want after listCompanion.Add({"jony", New String() {"age: 25", "gender: boy"}})
can repeat For Each kvp In listCompanion
There are three problems that don't allow your code to compile.
First you miss a couple of curly braces in the initialization of the listCompanion,
Dim listCompanion = New Dictionary(Of String, String()) From
{ {"dessy", New String() {"age: 21", "gender: girl"}}}
Second there are too many curly braces when you add a new element to the listCompanion.
If listCompanion.Count < 2 Then 'Error here
listCompanion.Add("jony", New String() {"age: 25", "gender: boy"})
End If
Finally you can't change the listCompanion while you loop over it, so if you want to add that KeyValuePair also to the Listbox items then you should add it before starting the loop
Dim kvp As KeyValuePair(Of String, String())
ListBox1.Items.Clear()
If listCompanion.Count < 2 Then 'Error here
listCompanion.Add("jony", New String() {"age: 25", "gender: boy"})
End If
For Each kvp In listCompanion
Dim member As String = String.Format("{0} = {1} - {2}", kvp.Key, kvp.Value(0), kvp.Value(1))
ListBox1.Items.Add(member) 'I want every additions will enter the listbox
Next

Better VB.NET String Scrambler?

I needed a function to take a string phrase and scramble it. So I wrote this, but I'm wondering if there is a more efficient/faster way to do it?
Public Function Scramble(phrase As String) As String
Dim rand As New Random()
Dim newPhrase As String = ""
Dim clist As New List(Of String)
' break phrase into characters and add to list
For i As Integer = 1 To Len(phrase)
clist.Add(Mid(phrase.ToLower(), i, 1))
Next
' remove from list randomly and add to new string
Do While clist.Count > 0
Dim r As Integer = rand.Next(0, clist.Count)
newPhrase &= clist(r)
clist.RemoveAt(r)
Loop
Return newPhrase
End Function
Here's Plutonix's one-liner:
Public Function Scramble(ByVal phrase As String) As String
Static rand As New Random()
Return New String(phrase.ToLower.ToCharArray.OrderBy(Function(r) rand.Next).ToArray)
End Function
...and here's an alternate version of your longer form:
Public Function Scramble(ByVal phrase As String) As String
Static rand As New Random()
Dim sb As New System.Text.StringBuilder
Dim chars As New List(Of Char)(phrase.ToLower.ToCharArray)
While chars.Count > 0
Dim r As Integer = rand.Next(0, chars.Count)
sb.Append(chars(r))
chars.RemoveAt(r)
End While
Return sb.ToString
End Function

How can i serialize and deserialize a dictionary in vb.net?

I am working with an application that needs to store large dictionaries of 40 000+ keys and values in a file, and then load them back into dictionaries on startup... Right now i am using a simple character separation with split and a for each loop on startup like:
key1=value1|key2=value2|key3=value3 etc...
however, i am looking for a more efficient way of serializing and deserializing the dictionaries... also with size of the serialized data in mind as there is quite a lot of entries.
You could make use of BinaryFormatter
On my mid end machine: save took: 390ms load took: 359ms data saved was about 1500kb
'save
Dim dict = New Dictionary(Of String, String)
For i = 1 To 40000
dict.Add("key" & i, "value" & i)
Next
Dim fs As IO.FileStream = New IO.FileStream("d:\test\test.bin", IO.FileMode.OpenOrCreate)
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
bf.Serialize(fs, dict)
fs.Close()
'load
Dim fsRead As New IO.FileStream("d:\test\test.bin", IO.FileMode.Open)
Dim objTest As Dictionary(Of String, String) = bf.Deserialize(fsRead)
fsRead.Close()
This works well when using stacked dictionaries:
Dim DataDict as New Dictionary(Of String,Dictionary(Of String,String))
Here is a working example of embedded dictionaries being serialized for writing and reading:
Imports System.IO
Module Modules
Public Sub TestDict()
Dim DictsToSave As New Dictionary(Of String, Dictionary(Of String, String))
For DictsToHave = 1 To 10
Dim SingelDictData As New Dictionary(Of String, String)
For Values = 1 To 10000
SingelDictData.Add("Key " & Values.ToString(), "Value " & Values.ToString())
Next
DictsToSave.Add("Key " & DictsToHave.ToString(), SingelDictData)
Next
Dim WriteResult = WriteMultiSerializedDict("D:\TestDict.Bin", DictsToSave)
Dim ReadResult As Dictionary(Of String, Dictionary(Of String, String)) = ReadMultiSerializedDict("D:\TestDict.Bin")
End Sub
Public Function WriteMultiSerializedDict(ByVal FullPath As String, ByVal DataDict As Dictionary(Of String, Dictionary(Of String, String))) As Boolean
Try
Dim FileStream As IO.FileStream = New FileStream(FullPath, IO.FileMode.OpenOrCreate)
Dim BinFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
BinFormatter.Serialize(FileStream, DataDict)
FileStream.Close()
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Function ReadMultiSerializedDict(ByVal FullPath As String) As Dictionary(Of String, Dictionary(Of String, String))
Try
Dim DataDict As New Dictionary(Of String, Dictionary(Of String, String))
Dim FileStream As IO.FileStream = New FileStream(FullPath, IO.FileMode.Open)
Dim BinFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
DataDict = BinFormatter.Deserialize(FileStream)
FileStream.Close()
Return DataDict
Catch ex As Exception
Return Nothing
End Try
End Function
On my mid end dev machine, this took about 260 ms for the write and 545 for the read, with a file that measured at 3.70 mb. Important note: If you change any of the dict's keys (not values), the load bombs! So, as a matter of programming, always assemble your dicts in the same order. I've used this approach before, using 5 100 key/value pairs in the sub dictionary's, without issue or problem.

How to add List as value in Hashtable

In vb.net If I have HashTable,key is integer and the value is a list of integers, how to append integers to the value of a given key,
I have tried it but each time I found the integer last added only, (the list only has the last item added).
Here is my code , where dt is DataTable object
Dim dt = report.getEvaluationReportByObjectiveGroupId(29)
Dim data As New Hashtable()
Dim dataEntry As DictionaryEntry
Dim res As String
For Each row As DataRow In dt.Rows
Dim strYear = row.Item("Year")
Dim strData = row.Item("EmpCount")
If data.ContainsKey(strYear) Then
Dim newCountArr As List(Of Int32) = DirectCast(data(strYear), List(Of Int32))
' newCountArr.AddRange(data(strYear))
newCountArr.Add(strData)
' data.Remove(strYear)
' data.Add(strYear, newCountArr)
Else
Dim countArr As New List(Of Integer)
countArr.Add(strData)
data.Add(strYear, countArr)
End If
' data.Add(strYear, strData)
Next row
I would suggest to use the strongly typed Dictionary(Of Int32, List(Of Int32)) instead, it works similar. But anyway, here's the HashTable approach:
Dim table = New Hashtable
Dim list = New List(Of Int32)
For i = 1 To 999
list.Add(i)
Next
table.Add(1, list)
' somewhere else you want to read the list for a given key (here 1) '
Dim list1 As List(Of Int32) = DirectCast(table(1), List(Of Int32))
list.Add(1000) ' add another integer to the end of the list '
' note: you don't need to add the list to the HashTable again '
Edit: Since you've posted your code, here's the corrected:
For Each row As DataRow In dt.Rows
Dim strYear = row.Field(Of Int32)("Year")
Dim strData = row.Field(Of Int32)("EmpCount")
Dim list As List(Of Int32)
If data.ContainsKey(strYear) Then
list = DirectCast(data(strYear), List(Of Int32))
Else
list = New List(Of Int32)
data.Add(strYear, list)
End If
list.Add(strData)
Next row

Building a multidimensional array in vb.net

I'm trying to build up a multidimensional array which will hold two bits of info for each record in a database e.g. id, description.
This is what I am currently doing.
Dim mArray(,) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
The problem I have here is that it doesn't like the i in mArray(i,0). Anyone have any ideas about this? This is the error that is given Object reference not set to an instance of an object.
Thanks for any and all help.
Nalum
Why not rather make use of List Class and Dictionary Class
You can rather then create a List of Dictionaries, with the key and value both strings. The key can then represent your key (id and description in your example, and the value can be what ever was stored).
Something like
Dim values As New List(Of Dictionary(Of String, String))()
and then in the while loop something like
values.Add(New Dictionary(Of String, String)() From { _
{"id", cmdReader.Item("id")} _
})
values.Add(New Dictionary(Of String, String)() From { _
{"description", cmdReader.Item("description")} _
})
You could then use foreach
For Each value As Dictionary(Of String, String) In values
Dim id As String = value("id")
Dim description As String = value("description")
Next
Or a for
For i As Integer = 0 To values.Count - 1
Dim value As Dictionary(Of String, String) = values(i)
Dim id As String = value("id")
Dim description As String = value("description")
Next
Try this
Dim mArray(1,1) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
ReDim Preserve mArray(i,1)
End While
The problem is that you are not initializing the array.
This should work, until i will not reach the limits set in the initialization.
Dim mArray(100,100) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
But if the array limits are not known I suggest to follow astander's suggestion.
This works for me:
Dim values As New List(Of Dictionary(Of String, String))()
values.Add(New Dictionary(Of String, String)() From {{"quarter", q1.ToString}, {"year", y1.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q2.ToString}, {"year", y2.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q3.ToString}, {"year", y3.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q4.ToString}, {"year", y4.ToString}})
For Each value As Dictionary(Of String, String) In values
Dim quarter As String = value("quarter")
Dim year As String = value("year")
Debug.Print(quarter & "/" & year)
Next
Correct it by
Dim mArray(,) As String = ""