Group DataSet Column Values into Comma Separated String using LINQ - vb.net

How do I combine column values in a dataset using LINQ into a single string with comma separated values in VB.NET ?
I have one table with following structure
ID Name
728 Jim
728 Katie
728 Rich
How do I combine these into a single row like following
ID Name
728 Jim,Katie,Rich
Please note I am using a LINQ to Dataset so please respond in the applicable syntax.

Here is an example (using LINQ to objects, but should be easy to adjust for LINQ to DataSet):
Class Record
Public Property ID As Integer
Public Property Name As String
Sub New(id As Integer, name As String)
Me.ID = id
Me.Name = name
End Sub
End Class
Sub Main()
Dim recordList As New List(Of Record)
recordList.Add(New Record(728, "Jim"))
recordList.Add(New Record(728, "Katie"))
recordList.Add(New Record(728, "Rich"))
recordList.Add(New Record(729, "John"))
recordList.Add(New Record(729, "Michael"))
Dim v = From r As Record In recordList
Group By ID = r.ID Into Records = Group
Select ID, Name = String.Join(","c, Records.Select(Function(x) x.Name))
End Sub

This should do what you want:
Dim result = list.GroupBy(Function(a) a.ID) _
.Select(Function(g) New With {.ID = g.Key, .csvList = g.Select(Function(n) n.Name) _
.Aggregate(Function(accumulation, current) accumulation + "," + current)}) _
.ToList()

This is an example using LINQ to Dataset:
Dim grouped =
From row In dt.AsEnumerable()
Group row By id = row.Field(Of Integer)("ID") Into Group
Select ID, Name = String.Join(",", From i In Group Select i.Field(Of String)("Name"))

pretty late but i also ran into same problem and this is my solution. Hope this helps someone
Dim grouped =
a.AsEnumerable().
GroupBy(Function(row) row.Field(Of Integer)("ID")).
Select(Function(group, ID)
Return New With
{
.ID= ID,
.Name= String.Join(",", group.Select(Function(row) row.Field(Of String)("Name")))
}
End Function)

Related

vb.net Linq statement to find duplicates using fuzzy searching

I have a datatable containing:
ID as Integer = Primary Key.
Name as String
OtherFields ....
I have a function that can find duplicate names in the table
Private Function DuplicateComputerNames() As String
Dim ret As String = $"Duplicate Computer Names found in Table Computer.{vbCrLf}"
Dim computerTable As DataTable
computerTable = ComputerTableAdapter.GetData
Dim duplicates = computerTable.AsEnumerable().GroupBy(Function(i) i.Field(Of String)("Name")) _
.Where(Function(g) g.Count() > 1).Select(Function(g) g.Key)
For Each d In duplicates
ret = $"{ret}{vbTab}{d}{vbCrLf}"
Next
Return ret
End Function
This works perfectly.
Now sometimes the name has a prepend of "(POOL)" i.e. "Laptop-55 (POOL)"
I need a function that will find duplicates of just the Laptop-55 part.
i.e. If there is a Laptop-55 and a Laptop-55 (POOL)
I thought this code would do the job, but apparently not.
Private Function PoolComputerNames() As String
Dim ret As String = $"Possible Duplicate Computer Names found in Table Computer.{vbCrLf}"
Dim computerTable As DataTable
computerTable = ComputerTableAdapter.GetData
Dim duplicates = computerTable.AsEnumerable().GroupBy(Function(i) i.Field(Of String)("Name")) _
.Where(Function(g) g.Count() > 1).Select(Function(g) g.Key.Split("("c)(0).Trim())
For Each d In duplicates
ret = $"{ret}{vbTab}{d}{vbCrLf}"
Next
Return ret
End Function
Hoping that someone can point in the right direction.
Thanks.
Thanks for jmcilhinney in the comments I managed to solve my issue.
Private Function PoolComputerNames() As String
Dim count As Integer = 0
Dim ret As String = $"[count] possible duplicate Computer Names found in Table Computer.{vbCrLf}"
Dim computerTable As DataTable
computerTable = ComputerTableAdapter.GetData
Dim duplicates = computerTable.AsEnumerable().GroupBy(Function(i) i.Field(Of String)("Name").Split("("c)(0).Trim()) _
.Where(Function(g) g.Count() > 1).Select(Function(g) g.Key)
For Each d In duplicates
count += 1
ret = $"{ret}{vbTab}{d}{vbCrLf}"
Next
ret = ret.Replace("[count]", $"{count}")
Return ret
End Function

Distinct Rows From Vb.Net DataTable

I have a scenario, in which I have to apply distinct filter onto DataTable and find the rows only which are distinct,
I am using dt.DefaultView.ToTable(True, Columns) this statement but no effect.
Here is my chunk of code..
Try
Dim dTable As New DataTable()
dTable.Columns.Add("AutoID")
dTable.Columns.Add("AnotherID")
dTable.Columns.Add("CitY")
Dim row As DataRow = Nothing
For i As Integer = 0 To 4
row = dTable.NewRow()
row("AutoID") = i + 1
row("AnotherID") = i + 10
row("City") = "Vetican"
dTable.Rows.Add(row)
Next
dTable.Rows.Add(6, "11", "Oslo")
dTable.Rows.Add(7, "12", "Toronto")
Dim TobeDistinct As String() = {"AnotherID"}
Dim dtDistinct As DataTable = GetDistinctRecords(dTable, TobeDistinct)
Catch ex As Exception
End Try
and the method ..
Public Shared Function GetDistinctRecords(ByVal dt As DataTable, ByVal Columns As String()) As DataTable
Dim dtURecords As New DataTable()
dtURecords = dt.DefaultView.ToTable(True, Columns)
Return dtURecords
End Function
Here is the screen shot , which I want..
Which rows do you want to keep and which rows should be removed? If you just want to keep one row per AnotherID it seems to be arbitrary to keep Vetican instead of Oslo. Maybe you want to concat both as in Vetican, Oslo.
I would use Linq instead:
Dim resultTable = dTable.Clone() ' empty table same columns
Dim idGroups = dTable.AsEnumerable().GroupBy(Function(r) r.Field(Of String)("AnotherID"))
For Each grp In idGroups
Dim r As DataRow = resultTable.Rows.Add()
r.SetField("AutoID", grp.First().Field(Of String)("AutoID"))
r.SetField("AnotherID", grp.Key)
Dim cities = From row In grp Select row.Field(Of String)("City")
r.SetField("City", String.Join(", ", cities))
Next

Convert c# linq query to vb.net

I have some C# LINQ code and would like to convert it to vb.net. Can you help?
var userSessionId= 25;
ProjectsPerUser = db.tbProjekt.Where(s => s.tbUserProjects.Any(x => x.UserId == userSessionId)).ToList();
it was out of this raw sql query:
ProjectsPerUser = db.Database.SqlQuery(Of tbProjekt)("SELECT * FROM [16281468_general].[dbo].[tbProjekt] WHERE Id " _
& "IN (SELECT DISTINCT ProjectId FROM [16281468_general].[dbo].[tbUserProject] WHERE UserId = " & userSessionId & ")").ToList
now I want to convert it to vb.net but I have some problems with that.
That is my current try:
tables within context: tbProjekt and tbUserProjects
Dim dabcon As New production_TextEntitesContext
Dim ProjectsPerUsers As New List(Of tbProjekt)
Dim userSessionId As Integer = 111
ProjectsPerUsers = dabcon.tbProjekt.Where(Function(s) s.tbUserProjects.Any(Function(x) x.UserId = userSessionId)).ToList()
But, I got this error:
Late binding operations cannot be converted to expression tree
on line s.tbUserProjects.Any.
Maybe something like this would help. Just an example
Sub Main()
Dim projects As New List(Of Integer)
projects.Add(1)
projects.Add(2)
projects.Add(3)
Dim users As New Dictionary(Of String, Integer)
users.Add("john", 1)
users.Add("mary", 2)
Dim userName As String = "john"
Dim userProjects = From p In projects
Join u In users On p Equals u.Value
Where u.Key = userName
Select p, u.Key
For Each v In userProjects
Console.WriteLine("user: {0} project: {1}", v.Key, v.p)
Next
Console.ReadLine()
End Sub
Assuming you have navigation properties set up, this should work as well:
Dim userProjects=dabcon.tbUsers.Where(Function(u) u.Key=userName).Select(Function(u) u.Projects))
or query syntax:
Dim userProjects=from u in dabcon.tbUsers
where u.Key=userName
select u.Projects

Retrieve distinct values from datatable using linq vb.net

I am trying to retrieve all of the distinct values from a particular column in a datatable. The column name in the datatable is "Count". I have 2240 rows and I have 6 distinct values in the "Count" column. The problem is, when I execute the following code, it is giving me the number of rows rather than the 6 distinct values.
Dim counts = (From row In loadedData
Select row.Item("Count")).Distinct()
For Each i In counts
MsgBox(i)
Next
How can I modify this to retrieve the 6 distinct values, rather than it giving me the total number of rows?
You just have to select the column and use Enumerable.Distinct:
Dim distinctCounts As IEnumerable(Of Int32) = loadedData.AsEnumerable().
Select(Function(row) row.Field(Of Int32)("Count")).
Distinct()
In query syntax(i didn't know that even Distinct is supported directly in VB.NET):
distinctCounts = From row In loadedData
Select row.Field(Of Int32)("Count")
Distinct
You can use ToTable(distinct As Boolean, ParamArray columnNames As String()) method for this.
loadedData.DefaultView.ToTable(True, "Count")
This will return distinct Users for you. You can add multiple column names if you want.
Here is the msdn documentation.
https://msdn.microsoft.com/en-us/library/wec2b2e6(v=vs.110).aspx
you can also apply this logic if you want ,
first sort datatable through columName ,
then apply this logic
dtRecords.DefaultView.Sort = "columnName"
dtRecords = dtRecords.DefaultView.ToTable
Dim totalRecords As Integer = 0
Dim thNameStr As String = filter(dtRecords, "columnName", totalRecords )
Public Shared Function filter(ByVal dtRecords As DataTable, ByVal columnName As String, ByRef totalRecords As Integer) As String
Dim FilterStr As String = ""
Dim eachTotal As Integer = 0
totalRecords = 0
Dim lastName As String = ""
For rCount = 0 To dtRecords.Rows.Count - 1
If lastName <> "" And lastName <> dtRecords.Rows(rCount)("" & columnName) Then
FilterStr &= lastName & " - [" & eachTotal & "]"
eachTotal = 0
totalRecords += 1
End If
lastName = dtRecords.Rows(rCount)("" & columnName)
eachTotal += 1
Next
FilterStr &= lastName & " - [" & eachTotal & "]"
totalRecords += 1
Return FilterStr
End Function

convert a datatable

I have a datatable like this
X,Y,Z
0,0,A
0,2,B
0,0,C
1,0,A
1,0,C
2,2,A
2,2,B
2,0,C
3,2,B
3,1,C
4,3,A
4,0,B
4,1,C
5,3,A
5,2,B
5,0,C
and I want to convert it to something like this:
X,A,B,C
0,0,2,0
1,0, ,0
2,2,2,0
3, ,2,1
4,3,0,1
5,3,2,0
I tried with dataset and linq but not I wasn't lucky.
My code for linq:
Dim q = (From c In dt _
Select c("Z") Distinct) 'I found out which categories I have in Z column (my example :A,B,C)
Dim ldt(q.Count) As DataTable
For i = 0 To q.Count - 1
Dim sfil As String = q(i).ToString
Dim r = (From c In dt _
Select c Where c("Z") = sfil)
ldt(i) = r.CopyToDataTable
Next
So now I have 3 tables (ldt(0) with values for A, ldt(1) with values for B, ldt(2) with values for C)
and I was thinking to do something like leftJoin but anything that I tried is fail.
Any solution or even a better idea?
Thanks
So a new example it would be:
I have this table:
id,Price,Item
0,0,Laptop
0,2,Tablet
0,0,Cellphone
1,0,Laptop
1,0,Tablet
2,2,Laptop
2,2,Cellphone
2,0,Tablet
3,2,Cellphone
3,1,Tablet
4,3,Laptop
4,0,Cellphone
4,1,Tablet
5,3,Laptop
5,2,Cellphone
5,0,Tablet
and I would like to convert it to this:
X,Laptop,Tablet,Cellphone
0,0,2,0
1,0, ,0
2,2,2,0
3, ,2,1
4,3,0,1
5,3,2,0
The values for each of the columns Laptop, Tablet, Cellphone are the Y values from the first table.
I hope it make more sense now.
I believe you can create a DataTable with column names corresponding to the item names. Then you group the previous DataTable by id and use each grouping to populate a row. Forgive me if I get anything wrong. I don't work with VB or DataTables that much.
Dim itemNames = (From c In dt _
Select c("Item") Distinct)
Dim newDt as DataTable = new DataTable()
Dim idColumn As DataColumn = new DataColumn()
idColumn.DataType = System.Type.GetType("System.Int32")
idColumn.ColumnName = "id"
idColumn.ReadOnly = True
idColumn.Unique = True
newDt.Columns.Add(idColumn)
For Each itemName As String In itemNames
Dim column As DataColumn = new DataColumn()
column.DataType = GetType(Nullable(Of Integer))
column.ColumnName = itemName
column.ReadOnly = True
column.Unique = False
newDt.Columns.Add(column)
Next
Dim groupingById = From row in dt
Group By Id = row("id")
Into RowsForId = Group
For Each grouping In groupingById
Dim row as DataRow = newDt.NewRow()
row("id") = grouping.Id
For Each rowForId in grouping.RowsForId
row(rowForId("Item")) = rowForId("Price")
Next
newDt.Rows.Add(row)
Next