VB.NET - Extracting text inside quotation in a complex string - vb.net

I have a string looking like this:
a:391:i:0;s:12:"jnKKPkvpNnfn";i:1;s:12:"ic9VAk3PvQ3j";i:2;s:12:"PEBFuE6bGepr";i:3;s:12:"bwuxRkH6QbGp";i:4;s:12:"LSRDQbAKXc9q";i:5;s:12:"eLuVbSAxQCgo";}
And I want to get the text inside the quotations and send them to a listbox.
I know sort of how to do it, but in an ineffective way that might now work... So I'm asking for advice with an example on how to do it.
Thanks

This should get you started; the method will run through an input string and return an array of strings that are contained within quotes.
string[] ParseQuotes(string input)
{
List<string> matches = new List<string>();
bool open = false;
int index = -1;
for (int i = 0; i < input.Length; i++)
{
if (input[i] == '"')
{
if (!open)
{
open = true;
index = i;
}
else
{
open = false;
string match = input.Substring(index + 1, index - i - 1);
matches.Add(match);
}
}
}
return matches.ToArray();
}
Converted to VB...
Private Function ParseQuotes(input As String) As String()
Dim matches As New List(Of String)()
Dim open As Boolean = False
Dim index As Integer = -1
For i As Integer = 0 To input.Length - 1
If input(i) = """"C Then
If Not open Then
open = True
index = i
Else
open = False
Dim match As String = input.Substring(index + 1, index - i - 1)
matches.Add(match)
End If
End If
Next
Return matches.ToArray()
End Function

In your main code:
cbYourcomboBox.Items.Clear()
cbYourcomboBox.Items.AddRange(GetList(str).ToArray)
and then the function itself:
Public Function GetList(ByVal str As String) As List(Of String)
Dim ar As String()
Dim ar2 As List(Of String) = New List(Of String)
ar = Split(str, Chr(34))
' making sure there is a matching closing quote with - (UBound(ar) And 1)
For a As Integer = 1 To UBound(ar) - (UBound(ar) And 1) Step 2
ar2.Add(ar(a))
Next a
Return ar2
End Function

Related

Sample code of aleaGPU is not working in VB

C# code:
[GpuManaged, Test]
public static void ActionFactoryWithClosure2()
{
var MyGPU = Gpu.Get(0);
var arg1 = Enumerable.Range(0, Length).ToArray();
var arg2 = Enumerable.Range(0, Length).ToArray();
var result = new int[Length];
Func<int[], Action<int>> opFactory = res => i =>
{
res[i] = arg1[i] + arg2[i];
};
MyGPU.For(0, arg1.Length, opFactory(result));
}
VB.NET code:
<GpuManaged>
Public Shared Function GPU_TEST_VB_20170920()
Dim MyGPU As Alea.Gpu = Gpu.Default
Dim arg1 = Enumerable.Range(0, Length).ToArray()
Dim arg2 = Enumerable.Range(0, Length).ToArray()
Dim result = New Integer(Length - 1) {}
Dim expected = New Integer(Length - 1) {}
Dim opFactory As Func(Of Integer(), Action(Of Integer)) = Function(res) Function(i)
res(i) = arg1(i) + arg2(i)
End Function
Dim op As Action(Of Integer) = Function(i) InlineAssignHelper(result(i), arg1(i) + arg2(i))
Dim op2 As Action(Of Integer) = Sub(i)
result(i) = arg1(i) + arg2(i)
End Sub
MyGPU.[For](0, result.Length, Function(i) InlineAssignHelper(result(i), arg1(i) + arg2(i))) 'Error : The given key was not present in the dictionary.
MyGPU.For(0, arg1.Length, opFactory(result)) 'Error : The given key was not present in the dictionary.
MyGPU.For(0, arg1.Length, op) 'Error : The given key was not present in the dictionary.
MyGPU.For(0, arg1.Length, op2) 'Error : Cannot get field ""$VB$Local_result. Possible reasons: -> Static field Is Not supported."
End Sub
In case of C#, I can run sample code, but in VB, I Got error message (please see above code lines)
What Should I Do
Same condition : VS 2017, Windows 10, AleaGPU 3.0.3

(VB.NET) Find all duplicates in a list of objects based on multiple properties

I have a list of CommissionStatement objects which i created. I need to create a new list which only holds the duplicates found in this list based on 3 properties: Firm; Provider; and Total (ie each of these 3 have to be the same in 2 or more objects for it to be recognized as a duplicate)
Object is a simple object of strings at the moment.
Private Class CommissionStatement
Property Provider As String
Property Firm As String
Property Source As String
Property Media As String
Property Total As String
Property Received As String
End Class
I have a list of all CommissionStatments as follows:
Dim fileLocation As String = importText.Text
Dim csvText As String = My.Computer.FileSystem.ReadAllText(fileLocation).Replace(", ", " ")
Dim providerString As String = ""
Dim allStatements = New List(Of CommissionStatement)
Dim countIndex As Integer = 0, maxIndex As Integer = csvText.Split(vbLf).Length
For Each line As String In csvText.Split(vbLf)
'' Remove the top row
countIndex += 1
If countIndex = 1 Then
Continue For
End If
statementProgress.Value = ((countIndex / maxIndex) * 100)
'' Build the New commissionStatement object and add it to the allStatements list
If Not line = "" Then
Dim commissionStatement = New CommissionStatement
With commissionStatement
.Provider = line.Split(",")(0)
.Firm = line.Split(",")(1)
.Source = line.Split(",")(2)
.Media = line.Split(",")(3)
.Total = line.Split(",")(4)
End With
providerString &= commissionStatement.Provider & ","
allStatements.Add(commissionStatement)
End If
Next
First post on StackOverflow so sorry if its not very clear! The duplicate list needs to also be a list of CommissionStatements which contain the duplicates from the allStatements list based on Firm Provider and Total
Your best bet is to use a lambda expression. The function below should do what you ask.
Private Function GetDuplicateCommisionStatements(tempStatement As CommissionStatement) As List(Of CommissionStatement)
Return allStatements.FindAll(Function(x) x.Firm = tempStatement.Firm And x.Provider = tempStatement.Provider And x.Total = tempStatement.Total)
End Function
And use it like this..
duplicatelist = GetDuplicateCommisionStatements(testCommisionStatement)
using your own object names of course.
Incidentally, you could shorten the sub using the With statement like below
Private Function GetDuplicateCommisionStatements(tempStatement As CommissionStatement) As List(Of CommissionStatement)
With tempStatement
Return allStatements.FindAll(Function(x) x.Firm = .Firm And x.Provider = .Provider And x.Total = .Total)
End With
End Function

Sort List(of Object) by object properties

I'm trying to achieve something where the answer is already given for. But it's in c# and I don't have any knowledge what-so-ever over c# so I'm looking for a vb.net alternative.
I made a class called BomItem which has several properties like quantity, description etc.
I add these BomItems into a List(of BomItem) but now I would like to sort them according to a property. How can you sort the items based on the ItemNumber property?
Here is the link to the c# solution I found.
My class code
Public Class BomItem
Public Property ItemNumber As String
Public Property Description As String
Public Property Quantity As Double
Public Property Material As String
Public Property Certificate As String
End Class
How I add the BomRow objects
_NewBomList.Add(New BomItem() With {
.ItemNumber = oRow.ItemNumber,
.Description = oPropSet.Item("Description").Value,
.Quantity = oRow.TotalQuantity,
.Material = oPropSet.Item("Material").Value,
.Certificate = CustomPropertySet.Item("Cert.").Value})
Comparer
Public Class NaturalSort
Implements IComparer
Public Function Compare(ByVal x As Object,
ByVal y As Object) As Integer Implements IComparer.Compare
' [1] Validate the arguments.
Dim s1 As String = x
If s1 = Nothing Then
Return 0
End If
Dim s2 As String = y
If s2 = Nothing Then
Return 0
End If
Dim len1 As Integer = s1.Length
Dim len2 As Integer = s2.Length
Dim marker1 As Integer = 0
Dim marker2 As Integer = 0
' [2] Loop over both Strings.
While marker1 < len1 And marker2 < len2
' [3] Get Chars.
Dim ch1 As Char = s1(marker1)
Dim ch2 As Char = s2(marker2)
Dim space1(len1) As Char
Dim loc1 As Integer = 0
Dim space2(len2) As Char
Dim loc2 As Integer = 0
' [4] Collect digits for String one.
Do
space1(loc1) = ch1
loc1 += 1
marker1 += 1
If marker1 < len1 Then
ch1 = s1(marker1)
Else
Exit Do
End If
Loop While Char.IsDigit(ch1) = Char.IsDigit(space1(0))
' [5] Collect digits for String two.
Do
space2(loc2) = ch2
loc2 += 1
marker2 += 1
If marker2 < len2 Then
ch2 = s2(marker2)
Else
Exit Do
End If
Loop While Char.IsDigit(ch2) = Char.IsDigit(space2(0))
' [6] Convert to Strings.
Dim str1 = New String(space1)
Dim str2 = New String(space2)
' [7] Parse Strings into Integers.
Dim result As Integer
If Char.IsDigit(space1(0)) And Char.IsDigit(space2(0)) Then
Dim thisNumericChunk = Integer.Parse(str1)
Dim thatNumericChunk = Integer.Parse(str2)
result = thisNumericChunk.CompareTo(thatNumericChunk)
Else
result = str1.CompareTo(str2)
End If
' [8] Return result if not equal.
If Not result = 0 Then
Return result
End If
End While
' [9] Compare lengths.
Return len1 - len2
End Function
End Class
Use LINQ OrderBy:
_NewBomList.OrderBy(Function(bi) bi.ItemNumber)
and for descending:
_NewBomList.OrderByDescending(Function(bi) bi.ItemNumber)
If you want a numeric order in your string you have to convert it to an integer first:
_NewBomList.OrderBy(Function(bi) Integer.Parse(bi.ItemNumber))
Edit:
To provide a custom IComparer for the OrderBy extension you have to create a class which implements IComparer(Of String) where String are your ItemNumbers to compare:
Class ItemNumberComparer
Implements IComparer(Of String)
Public Function Compare(String x, String y)
Dim ix As String() = x.Split("."C)
Dim iy As String() = y.Split("."C)
Dim maxLen As Integer = Math.Max(ix.Length, iy.Length)
For i As Integer = 0 To maxLen - 2
If ix.Length >= i AndAlso iy.Length >= i Then
If Integer.Parse(ix(i)) < Integer.Parse(iy(i)) Then
Return -1 'If x.i is LT y.i it must be smaller at all
ElseIf Integer.Parse(ix(i)) > Integer.Parse(iy(i)) Then
Return 1 'If x.i is GT y.i it must be bigger all
End If
End If
Next
'This code is only executed if x and y differ at last number or have different ´number of dots
If ix.Length = iy.Length Then
Return Integer.Parse(ix(ix.Length - 1)).CompareTo(Integer.Parse(iy(iy.Length - 1))) 'Only last number differs
Else
Return ix.Length.CompareTo(iy.Length) 'The number with more dots is smaller
End If
End Function
End Class
Call syntax:
Dim comparer = new ItemNumberComparer()
_NewBomList.OrderByDescending(Function(bi) bi.ItemNumber, comparer)
This C# code from that other thread:
List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
equates to this VB code:
List(Of Order) SortedList = objListOrder.OrderBy(Function(o) o.OrderDate).ToList()
As you can see, very little changes. You just have to know the syntax for generics and lambda expressions.
You should be aware, though, that this code does NOT sort your list. It sorts the items in the list and then adds them to a new list in that order. This is perfectly fine for many applications but if you're using that same list elsewhere then you won't see the new order there. While there are a few variations, one way to actually sort the list in place is like this:
objListOrder.Sort(Function(o1, o2) o1.OrderDate.CompareTo(o2.OrderDate))
Another solution would be to implement the IComparable (see MSDN ref) interface. This interface is designed to sort your objects on a custom way :
Public Class BomItem
Implements IComparable
Public Property ItemNumber As String
Public Property Description As String
Public Property Quantity As Double
Public Property Material As String
Public Property Certificate As String
Public Function CompareTo(obj As Object) As Integer
Dim bom = CType(obj, BomItem)
If Not bom Is Nothing then
Return Me.ItemNumber.CompareTo(bom.ItemNumber)
Else
Throw New ArgumentException("Object is not a BomItem")
End If
End Class
and you can sort the list this way :
Dim myList As New List(Of BomItem)
'Code to add your BomItems
myList.Sort()
This will actually sort your list, it does not create a new list.

ComboBox FindString Contains

I have such entries in Winforms ComboBox:
Font 8 pt
Font 9 pt
Font 10 pt
Font 12 pt
Font 14 pt
Then I have search string " 9 ".
Is here native way to find index by search string without looping?
I try this:
Dim a As Integer = myComboBox.FindString(" 9 ", 0)
... but without good result.
First, no, there is no available method in the framework that searches for sub-string in combobox items and returns the index of the first item which contains the search parameter.
But even ComboBox.FindString uses a loop as you can see in the source.
So there is nothing bad in using one, you could write an extension method for this:
public static class ControlExtensions
{
public static int FindSubStringIndex(this ComboBox combo, string subString, StringComparison comparer = StringComparison.CurrentCulture)
{
// Sanity check parameters
if(combo == null) throw new ArgumentNullException("combo");
if (subString == null) {
return -1;
}
for (int index = 0; index < combo.Items.Count; index++)
{
object obj = combo.Items[index];
if(obj == null) continue;
string item = Convert.ToString(obj, CultureInfo.CurrentCulture);
if (string.IsNullOrWhiteSpace(item) && string.IsNullOrWhiteSpace(subString))
return index;
int indexInItem = item.IndexOf(subString, comparer);
if (indexInItem >= 0)
return index;
}
return -1;
}
}
Now you can use it in this way:
int index = combo.FindSubStringIndex("9");
Whoops, VB.NET:
Public Module ControlExtensions
<System.Runtime.CompilerServices.Extension> _
Public Function FindSubStringIndex(combo As ComboBox, subString As String, Optional comparer As StringComparison = StringComparison.CurrentCulture) As Integer
' Sanity check parameters
If combo Is Nothing Then
Throw New ArgumentNullException("combo")
End If
If subString Is Nothing Then
Return -1
End If
For index As Integer = 0 To combo.Items.Count - 1
Dim obj As Object = combo.Items(index)
If obj Is Nothing Then
Continue For
End If
Dim item As String = Convert.ToString(obj, CultureInfo.CurrentCulture)
If String.IsNullOrWhiteSpace(item) AndAlso String.IsNullOrWhiteSpace(subString) Then
Return index
End If
Dim indexInItem As Integer = item.IndexOf(subString, comparer)
If indexInItem >= 0 Then
Return index
End If
Next
Return -1
End Function
End Module

how to sort list with strings containing numbers?

I have a Tlist that contains addresses. When I sort the list, numbers in the address are considered a string, and it doesn't sort correctly. How should I sort the list ascending?
Dim sortme As List(Of data) = tempdata 'main list containing addresses as strings.
sortme.Sort(Function(p1 As data, p2 As data) numorder(p1.Value).CompareTo(numorder(p2.Value)))
Private Function numorder(ByVal str As String)
Try
Dim words() As String = str.Split(" "c) 'read string up to first space (for number)
Return Convert.ToInt32(words(0))
Catch ex As Exception
End Try
End Function
Example of current output:
1001 street name
103 street name
1021 street name
It should be:
103 street name
1001 street name
1021 street name
The idea is to write your own comparer which will firs consider the number prefix and then the string itself. This comparer can be then used anywhere, for instance in LINQ OrderBy(). Here an example in c# see full VB.NET version below.
public class StreetComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int indexOfSpaceX = x.IndexOf(' ');
string numericalPartX = x.Substring(0, indexOfSpaceX);
int indexOfSpaceY = y.IndexOf(' ');
string numericalPartY = y.Substring(0, indexOfSpaceY);
int numberX;
int numberY;
if(!int.TryParse(numericalPartX, out numberX) ||
!int.TryParse(numericalPartY, out numberY))
{
//Some code to handle the case where number is missing
throw new ArgumentException();
}
if (numberX!=numberY)
{
return numberX-numberY;
}
string textPartX = x.Substring(indexOfSpaceX + 1);
string textPartY = x.Substring(indexOfSpaceY + 1);
return String.Compare(textPartX, textPartY, true, CultureInfo.CurrentCulture);
}
}
class Program
{
static void Main(string[] args)
{
var myStreets = new[] {"01 aaa", "02 bbb"};
var result = myStreets.OrderBy(s => s, new StreetComparer());
}
}
Now a VB.NET version adapted exactly to your use case a List with classes sorted by property:
Public Class StreetComparer
Implements IComparer(Of String)
Public Function Compare(x As String, y As String) As Integer
Dim indexOfSpaceX As Integer = x.IndexOf(" "C)
Dim numericalPartX As String = x.Substring(0, indexOfSpaceX)
Dim indexOfSpaceY As Integer = y.IndexOf(" "C)
Dim numericalPartY As String = y.Substring(0, indexOfSpaceY)
Dim numberX As Integer
Dim numberY As Integer
If Not Integer.TryParse(numericalPartX, numberX) OrElse Not Integer.TryParse(numericalPartY, numberY) Then
'Some code to handle the case where number is missing
Throw New ArgumentException()
End If
If numberX <> numberY Then
Return numberX - numberY
End If
Dim textPartX As String = x.Substring(indexOfSpaceX + 1)
Dim textPartY As String = x.Substring(indexOfSpaceY + 1)
Return [String].Compare(textPartX, textPartY, True, CultureInfo.CurrentCulture)
End Function
End Class
Public Class Person
Public Property Value() As String
Get
Return m_Value
End Get
Set
m_Value = Value
End Set
End Property
Private m_Value As String
Public Sub New(value__1 As String)
Value = value__1
End Sub
End Class
Class Program
Private Shared Sub Main(args As String())
Dim sortme As New List(Of Person)(New () {New Person("1001 street name"), New Person("103 street name"), New Person("1021 street name")})
Dim result = sortme.OrderBy(Function(p) p.Value, New StreetComparer())
For Each person As var In result
Console.WriteLine(person.Value)
Next
Console.ReadKey()
End Sub
End Class