VB.NET copy a 2-dimenion List into a one dimension list - vb.net

In my original code I have a list object containing 2 columns, Word and Percent. I sort the list but only want to return the list containing just the Word
Here is some example code broken down into something simple:
Public Function SortMyWords() as list(of string)
Dim Words As WordsToSort
Dim ListofWords As New List(Of WordsToSort)
Words.Word = "John"
Words.Percent = "10"
ListofWords.Add(Words)
Words.Word = "Robert"
Words.Percent = "1"
ListofWords.Add(Words)
ListofWords = ListofWords.OrderBy(Function(x) x.Percent).ToList()
End Sub
Public Structure WordsToSort
Public Word As String
Public Percent As String
Public Sub New(ByVal _word As String, ByVal _percent As String)
Word = _word
Percent = _percent
End Sub
End Structure
At the end of the SortMyWords function, I want to return just the Word column back as a list, I'm not sure if I can do this direct - i.e.
Return Listofwords(column Word) or whether I need to copy my ListofWords into a new list, just containing the Column Word - something like this (which doesn't work)
Dim Newlist As New List(Of String)
Newlist.AddRange(ListofWords(Words.Word))
Return NewList
Any suggestions on whether I should do this completely differently (and better) would be really appreciated as I am trying to get my head around objects and although I use them all the time, I'm new to structures and list objects.
Thanks for any help, this has been driving me crazy for an hour now.

I think you're close. Try:
ListOfWords
.OrderBy(Function(x) x.Percent)
.Select(Function(x) x.Word)
.ToList()
If you prefer, you can also use the LINQ syntax:
(from w in ListOfWords
orderby w.Percent ascending
select w.Word).ToList()
Note that the return type is a List(Of String) and not a List(Of WordsToSort) anymore. So you cannot assign it back to the variable ListOfWords again like you do in your sample code.

Related

Combining two list, only records with 1 specific unique property

I'm combining two lists in visual basic. These lists are of a custom object. The only record I want to combine, are the once with a property doesn't match with any other object in the list so far. I've got it running. However, the first list is just 1.247 records. The second list however, is just short of 27.000.000 records. The last time I successfully merged the two list with this restriction, it took over 5 hours.
Usually I code in C#. I've had a similar problem there once, and solved it with the any function. It worked perfectly and really fast. So as you can see in the code, I tried that here too. However it takes way too long.
Private Function combineLists(list As List(Of Record), childrenlist As List(Of Record)) As List(Of Record) 'list is about 1.250 entries, childrenlist about 27.000.000
For Each r As Record In childrenlist
Dim dublicate As Boolean = list.Any(Function(record) record.materiaalnummerInfo = r.materiaalnummerInfo)
If Not dublicate Then
list.Add(r)
End If
Next
Return list
End Function
The object Record looks like this ( I wasn't sure how to make a custom object in VB, and this looks bad, but it worked):
Public Class Record
Dim materiaalnummer As String
Dim type As String 'Config or prefered
Dim materiaalstatus As String
Dim children As New List(Of String)
Public Property materiaalnummerInfo()
Get
Return materiaalnummer
End Get
Set(value)
materiaalnummer = value
End Set
End Property
Public Property typeInfo()
Get
Return type
End Get
Set(value)
type = value
End Set
End Property
Public Property materiaalstatusInfo()
Get
Return materiaalstatus
End Get
Set(value)
materiaalstatus = value
End Set
End Property
Public Property childrenInfo()
Get
Return children
End Get
Set(value)
children = value
End Set
End Property
End Class
I was hoping that someone could point me in the right direction to shorten the time needed. Thank you in advance.
I'm not 100% sure what you want the output to be such as all differences or just ones from the larger list etc but I would definitely try do it with LINQ! Basically sql for vb.net data so would something similar to this:
Dim differenceQuery = list.Except(childrenlist)
Console.WriteLine("The following lines are in list but not childrenlist")
' Execute the query.
For Each name As String In differenceQuery
Console.WriteLine(name)
Next
Also side-note i would suggest not calling one of the lists "list" as it is bad practice and is a in use name on the vb.net system
EDIT
Please try this then let me know what results come back.
Private Function combineLists(list As List(Of Record), childrenlist As List(Of Record)) As List(Of Record) 'list is about 1.250 entries, childrenlist about 27.000.000
list.AddRange(childrenlist) 'combines both lists
Dim result = From v In list Select v.materiaalnummerInfo Distinct.ToList
'result hopefully may be a list with all distinct values.
End Function
Or Don't combine them if you dont want to.

extract list of string from list of custom class

i have a list(of custom class)
and i want to extract a list of all 'name' String, from it, through linq
I know how to do with a loop, but i need to get it with a linear, brief linq instruction.
i've checked this help
C# Extract list of fields from list of class
but i have problem in linq correct syntax
in particular because i would like to extract a New List(Of String)
Class Student
Sub New(ByVal NewName As String, ByVal NewAge As Integer)
Name = NewName
Age = NewAge
End Sub
Public Name As String
Public Age As Integer
End Class
Public Sub Main
Dim ClassRoom as New List(Of Student) From {New Student("Foo",33), New Student("Foo2",33), New Student("Foo3",22)}
Dim OneStudent as Student = ClassRoom(0)
Dim AllStudentsNames As New List(Of String) From {ClassRoom.Select(Function(x) x.Name <> OneStudent.Name).ToList}
End Sub
But something wrong...
Any help?
P.S. Since c# it's close to vb.Net, also c# helps are well welcome.
First, you don't need to create a new list From the one returned by the LINQ method. It's already in a new list at that point, so you can just set AllStudentsNames equal directly to what the ToList method returns.
Second, you are not selecting the name. You are selecting the result of the equality test to see if the names are different. In other words, when you say Select(Function(x) x.Name <> OneStudent.Name), that returns a list of booleans, where they true if the names are different and false if the names are the same. That's not what you want. You want the list of names, so you need to select the name.
Third, if you need to filter the list so that it only returns ones where the name is different, then you need to add a call to the Where method.
Dim AllStudentsNames As List(Of String) = ClassRoom.
Where(Function(x) x.Name <> OneStudent.Name).
Select(Function(x) x.Name).
ToList()

Convert Database Linq Query Results to String List

I am trying to use a LINQ query to grab some data from a database, and since I am grabbing just one column of data I want to store it within a string list. This is the code I have.
Dim POList As New List(Of String)
Using dbContext As New DBLINQDataContext
Dim query = (From o In dbContext.Orders
Where o.Order_Number.StartsWith(JobNumber)
Select o.Order_Number)
POList = query.ToList()
End Using
MessageBox.Show(POList.ToString())
When I run this the data in the MessageBox is
System.Collections.Generic.List`1[System.String]
There is no table data, even though I know there are actual data points for me to be getting :\
POList.ToString() will display the name of the object type.
You can use string.Join(",", POList.ToString()).
You can also define an extension method StringJoin() to show your list as string if you are going to use it frequently.
Here is an extension method that you can use:
public static StringExtensions
{
public static string StringJoin(this IEnumerable<string> strings, string seperator)
{
if (strings == null) return null;
return string.Join(seperator, strings);
}
}
Since this was a vb.net question, I translated #vendettamit 's excellent answer for the benifit of future vb readers.
Public Module StringExtensions
<Extension()>
Public Function StringJoin(MyStrings As IEnumerable(Of String), separator As String) As String
If MyStrings Is Nothing Then
Return Nothing
Else
Return String.Join(separator, MyStrings)
End If
End Function
End Module
To use the extension...
Dim l As New List(Of String) From {"Mathew", "Mark", "Luke", "John"}
Dim s As String = l.StringJoin(", ")
Debug.Print(s)

Readonly in keyvaluepair

Well I have created a program that takes some files (Mp3) and change their tags
recently I wanted to add some new Subs (like: Take the songs name and make every letter in it upercase). The problem is that i use a list with its items to be keyvaluepairs
Public MP3List As New List(Of KeyValuePair(Of String, String))
When i tried to edit the key or value of any Item in that list i get an error (That this is READONLY)
Example:
For Each Song In MP3List
Song.Key = "Something"
Next
I add items like this :
Private Function OpenAFile()
Dim MP3List1 = MP3List
Dim oFileDialog As New OpenFileDialog
oFileDialog.Title = "Επέλεξε ένα MP3 Άρχειο"
oFileDialog.Filter = "MP3 Files|*.mp3|All Files|*.*"
oFileDialog.Multiselect = True
Dim Path As String = ""
Dim Name As String = ""
Dim NewPair As New KeyValuePair(Of String, String)
If oFileDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
For Each sPath In oFileDialog.FileNames
Path = New String(sPath)
Name = New String(Strings.Split(Path, "\").ToList(Strings.Split(Path, "\").ToList.Count - 1))
NewPair = New KeyValuePair(Of String, String)(Name, Path)
If Not MP3List1.Contains(NewPair) Then MP3List1.Add(NewPair)
Next
End If
Return MP3List1
End Function
So the idea is this: Each time i press A button to add a song it will run the function OpenAFile() and it was working fine then . Now that i want to change a key or value i get this error
Thanks for the Help and sorry for bad english
The Keys in a KeyValuePair are readonly because they are often used as the key in a hash table. Changing the key would cause issues where you would lose your item in the hash.
If you want to do something like this, you could always create your own data type that stores a key and value. An overly simplified example would be as follows.
Public Structure PathNamePair
Public Property Path As String
Public Property Name As String
Public Sub New(path As String, name As String)
Me.Path = path
Me.Name = name
End Sub
End Structure
I will note that in order to get better performance with your Contains method, you should also implement IEquatable(Of T), but that's probably beyond the scope of this question. I will also note that it is not best practice to have a ValueType (Structure) that is mutable.

SQL LINQ Query: Selecting specific column

Today I am needing to write LINQ queries in VB.net to a database table, but am new to SQL/LINQ. This function below is meant to fill a list of strings with all of the possible "Questions" in the database table that match the QuestionType.
However, I only want to select one single column, the QuestionText column, and not all of the data, whenever I have a match.
Public Shared Function RetrieveQuestions(ByVal QuestionType) As List(Of String)
Dim db As New DBDataContext()
db.CommandTimeout = 300
Dim ListOfQuestions As List(Of String) = New List(Of String)
While True
Dim questionList As List(Of Question) = db.Questions.ToList
Dim question As List(Of String) = (From q As Question In questionList Where q.FormType = QuestionType Select q.QuestionText).ToList
Dim i As List(Of String) = question
If (question IsNot Nothing) Then
ListOfQuestions(ListOfQuestions.Count) = i.QuestionText //ERROR
Else
Exit While
End If
End While
Return ListOfQuestions
End Function
In the function above i am encountering an error when trying to update my list with the new QuestionText. "QuestionText is not a member of System.Collections.Generic.List(Of String)". QuestionText is defined as a varchar in my SQL database, so I know that it is definitely a string. I am not trying to set QuestionText to a list of strings, but rather add it to the end of a list of strings.
Direct answer: you'd need to put the whole If (question IsNot Nothing) Then block in a loop like For Each. As the compiler correctly informs - the i variable holds the whole list, not one of its items. Perhaps you forgot you left the LINQ query?
A better solution: I believe you could just use AndAlso q.QuestionText IsNot Nothing - it spares you the need to allocate a new list and to fill it one by one - the following code should do the trick.
Public Shared Function RetrieveQuestions(ByVal QuestionType) As List(Of String)
Dim db As New DBDataContext()
db.CommandTimeout = 300
Dim ListOfQuestions As List(Of String) = (
From q As Question In db.Questions.ToList
Where
q.FormType = QuestionType
AndAlso q.QuestionText IsNot Nothing
Select q.QuestionText
).ToList
Return ListOfQuestions
End Function