LINQ - querying top 5 with rank number - vb.net

How do I return a top 5 with rank number using linq?
Dim Top5 = From A In DAO.Cache.Select(Of VO.Empresa).Take(5) Select A.Nome
I would like this result:
Rank Name
1 "Example Name"
2 "Example Name"
3 "Example Name"
4 "Example Name"
5 "Example Name"

You need to use the Select overload which provides the index:
Dim Top5 = DAO.Cache.Take(5).Select(Function(A, Index) New With { .Rank = Index, .Name = A.Nome })
(I kept the property spelling .Nome - though I suspect it may need to be .Name)

If grdDetail.RowCount < 10 Then
grdDetail.CurrentRow.Cells(OrderNo.Name).Value = "00" & grdDetail.RowCount
ElseIf grdDetail.RowCount > 10 And grdDetail.RowCount < 100 Then
grdDetail.CurrentRow.Cells(OrderNo.Name).Value = "0" & grdDetail.RowCount
Else
grdDetail.CurrentRow.Cells(OrderNo.Name).Value = grdDetail.RowCount
End If

I'm not entirely sure I understand your question entirely: but I'm assuming you want to order your list to produce the top 5 in Rank - ascending order?
You can quite easily do this with the built in LINQ ordering syntax:
VB:
Dim Top5 = From o in objects Order By o.Rank Ascending Select o
C#: var top5 = from o in objects orderby o.Rank ascending select o
(surprising similar in this case /giggle)
For example, you could do the following:
C#:
void Main()
{
List<MyObject> objs = new List<MyObject>();
objs.Add(new MyObject{ Rank = 1, Message = "NUMBER ONE"});
objs.Add(new MyObject{ Rank = 3, Message = "NUMBER THREE"});
objs.Add(new MyObject{ Rank = 5, Message = "NUMBER FIVE"});
objs.Add(new MyObject{ Rank = 4, Message = "NUMBER FOUR"});
objs.Add(new MyObject{ Rank = 2, Message = "NUMBER TWO"});
var sortedobjs = from o in objs
orderby o.Rank ascending
select o;
Console.WriteLine(sortedobjs.ToList());
}
public class MyObject
{
public int Rank {get; set;}
public string Message {get; set;}
}
Which would spit out:
Rank Message
1 NUMBER ONE
2 NUMBER TWO
3 NUMBER THREE
4 NUMBER FOUR
5 NUMBER FIVE
HTH.

Related

How to count group of records using LINQ Query?

I have a database table that have a structure like this:
ID Integer Auto Incresement
Name VarChar
Status VarChar
Sample records:
ID Name Status
1 record 1 Outstanding
2 record 2 Outstanding
3 record 3 Aging
4 record 4 Outstanding
5 record 5 Aging
6 record 6 Outstanding
In the table, there are two main status: "Outstanding" and "Aging". I want to count how many records with status of "Outstanding" and how many records with status of "Aging" available in the table.
This is a sample LINQ Query:
Using DC = DataClassesDataContext.Create()
Dim dataTable = From Count(Outstanding), Count(Aging) In DC.MyTable _
Where item.Status = "Outstanding" OrElse item.Status = "Aging" _
Group By item.Status _
Select item
End Using
The expected result should be:
Outstanding Aging
4 2
Can you help me to design a LINQ to achive the result?
Try this:
Dim MyTable = { _
New With {.ID = 1, .Name = "record 1", .Status = "Outstanding"},
New With {.ID = 2, .Name = "record 2", .Status = "Outstanding"},
New With {.ID = 3, .Name = "record 3", .Status = "Aging"},
New With {.ID = 4, .Name = "record 4", .Status = "Outstanding"},
New With {.ID = 5, .Name = "record 5", .Status = "Aging"},
New With {.ID = 6, .Name = "record 6", .Status = "Outstanding"}
}
Dim dataTable = _
From item In MyTable
Group By Key = item.Status Into Xs = Group
Select New With {.Status = Key, .Count = Xs.Count()}
I get this result:
Try this :-
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var test = new List<Sample>();
test.Add(new Sample{ID=1,Name="record 1",Status="Outstanding"});
test.Add(new Sample{ID=2,Name="record 2",Status="Outstanding"});
test.Add(new Sample{ID=3,Name="record 3",Status="Aging"});
test.Add(new Sample{ID=4,Name="record 4",Status="Outstanding"});
test.Add(new Sample{ID=5,Name="record 5",Status="Outstanding"});
test.Add(new Sample{ID=6,Name="record 6",Status="Aging"});
var result = from row in test
group row by "Count" into g
where g.FirstOrDefault() != null
select new
{
//Status = g.Key,
Outstanding = g.Where(C => C.Status == "Outstanding").Count(),
Aging = g.Where(C => C.Status == "Aging").Count()
};
Console.WriteLine("Outstanding"+" "+"Aging");
foreach(var item in result)
{
Console.WriteLine(" "+item.Outstanding+" "+item.Aging);
}
}
}
public class Sample
{
public int ID {get;set;}
public string Name {get;set;}
public string Status {get; set;}
}
result :-
you can run above sample code using following link - https://dotnetfiddle.net/xC2NXm
suggest improvement :)

Linq Order and Group 2 Items in a List by Name

I have the following input:
Public Function GetProgramTitles() As List(Of ProgramTitle)
Dim x As New List(Of ProgramTitle)
x.Add(New ProgramTitle("Outlook.exe", "email1"))
x.Add(New ProgramTitle("Outlook.exe", "email2"))
x.Add(New ProgramTitle("Outlook.exe", "email1"))
x.Add(New ProgramTitle("Outlook.exe", "email2"))
x.Add(New ProgramTitle("Outlook.exe", "email1"))
x.Add(New ProgramTitle("Word.exe", "Doc1"))
x.Add(New ProgramTitle("Outlook.exe", "email2"))
x.Add(New ProgramTitle("Word.exe", "Doc2"))
x.Add(New ProgramTitle("Outlook.exe", "email1"))
Return x
End Function
I would like to take in this data and return something like this:
Outlook.exe - 7 (instances of program)
-email1 - 4
-email2 - 3
Word.exe - 2
-Doc1 - 1
-Doc2 - 1
This is what I have so far:
Dim data = GetProgramTitles()
Dim programs = From c In data Select New With {c.Program, c.Title,
.Programs =
From o In c.Program
Group o By c.Program Into Group
Select New With {.Title = c.Title,
.TitleGroup =
From o In Group
Group o By c.Title Into TitleGroup = Group
Select New With {.Program = Program, .Title = TitleGroup}}}
For Each p In programs
Console.WriteLine("Program: " & p.Program & " - " & p.Title & " - " & p.Program.Count)
Next
The return I'm getting is not sorted at all and I can't figure out how to fix this.
I'm not sure why you're trying to use Group By in inner query, not right within the main one.
Dim programs =
From d In data
Group d By dk = d.Program Into dg = Group, dc = Count()
Order By dc Descending
Select New With {
.Program = dk,
.Count = dc,
.Titles =
From t In dg
Group t By tk = t.Title Into tg = Group, tc = Count()
Select New With {
.Title = tk,
.Count = tc
}
}
I changed the returned anonymous type structure a little bit, so you have to change your For Each loop as well,
For Each p In programs
Console.WriteLine("Program: {0} - {1}", p.Program, p.Count)
For Each t In p.Titles
Console.WriteLine("Title: {0} - {1}", t.Title, t.Count)
Next
Next
prints
Program: Outlook.exe - 7
Title: email1 - 4
Title: email2 - 3
Program: Word.exe - 2
Title: Doc1 - 1
Title: Doc2 - 1

How to create a virtual column on a gridview based on a particular gridview columns

Please i have a project that i query the database using entity framework as my ORM. This is my query
Dim subjectSearch = From subSearch In DemoSchool.EssenceSubjectRegistrations Where subSearch.Session = drpSession.SelectedItem.Text _
AndAlso subSearch.Term = drpTerm.SelectedItem.Text AndAlso subSearch.RealClass.ClassSN = findClassSN.FirstOrDefault AndAlso _
subSearch.SubjectCode = drpSubject.SelectedValue _
Select New With {.SubjectRegSN = subSearch.SubjectRegSN,
.FirstName = subSearch.Student.FirstName,
.Surname = subSearch.Student.Surname,
.CA1 = subSearch.CA1,
.CA2 = subSearch.CA2,
.CA3 = subSearch.CA3,
.CA4 = subSearch.CA4,
.CA5 = subSearch.CA5}
Then i query my result so that i can be able to do some operation on it by doing this
Dim secSubjectSearch = (From jamie In subjectSearch Select jamie).ToList() _
.Select(Function(jamie) New With {.SubjectRegSN = jamie.SubjectRegSN,
.FirstName = jamie.FirstName,
.Surname = jamie.Surname,
.CA1 = jamie.CA1,
.CA2 = jamie.CA2,
.CA3 = jamie.CA3,
.CA4 = jamie.CA4,
.CA5 = jamie.CA5,
.MidTerm = CDbl(jamie.CA1 + jamie.CA2 + jamie.CA3 + jamie.CA4 + jamie.CA5) / 5})
The result of the second query is bounded to the gridview which renders properly as it is suppose to rendered. My problem is that i want to create a virtual column called Rank on the gridview after the .MidTerm bounded column that will display the position of each person record in the search result.
NAME CA1 CA2 CA3 CA4 CA5 MIDTERM RANK
James 50 50 60 40 60 52 3
Essty 100 50 50 50 50 60 2
Markus 100 40 50 60 50 60 2
Code 100 100 100 100 50 90 1
Above is a format of the gridview columns. I want column Rank to be a virtual column that is calculated based on the Midterm score of the students.Code VB scored 90 so his rank so be 1 and so on.Please i don't know how to calculate this rank column and the code to get the highest and the smallest.Really i need help thanks
Two ways.
Use Unbound column and calculate/display the rank
Have a RANK field and pre-calculate it and bound it, something like:
Dim secSubjectSearch = (From jamie In subjectSearch Select jamie).ToList() _
.Select(Function(jamie) New With {.SubjectRegSN = jamie.SubjectRegSN,
.FirstName = jamie.FirstName,
.Surname = jamie.Surname,
.CA1 = jamie.CA1,
.CA2 = jamie.CA2,
.CA3 = jamie.CA3,
.CA4 = jamie.CA4,
.CA5 = jamie.CA5,
.MidTerm = CDbl(jamie.CA1 + jamie.CA2 + jamie.CA3 + jamie.CA4 + jamie.CA5) / 5,
.RANK = -1}).ToList()
dim sorted = secSubjectSearch.Select(function(n) n.MidTerm).Distinct().OrderByDescending(function(n) n).ToList()
for each itm in secSubjectSearch
itm.RANK = sorted.IndexOf(itm.MidTerm) + 1
next
-- Not tested, wrote it with notepad...

objectdb select where query

I attempt to select some instance using where clause
public static List<RSSItem> getRSSItem(int x1, int x2) {
EntityManagerFactory emf = DBHandler.getEmf();
EntityManager em = DBHandler.getEm(emf);
String query =
"SELECT items FROM RSSItem items "
+ "WHERE items.id <= :x1 AND "
+ "items.id >= :x2";
List<RSSItem> results =
(List<RSSItem>) em.createQuery(query).
setParameter("x1", x1).
setParameter("x2", x2).
getResultList();
return results;
}
the RSSItem attributes :
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
String title;
String link;
String description;
String pubdate;
String content;
HashMap<String, Integer> keyword = new HashMap();
HashMap<String, Integer> keywordBefore = new HashMap();
// TreeMap <String, Integer> keyword = new TreeMap();
String feed;
the problem is it always return a list with 0 size. what's wrong with my select query?
With the values x1 = 1 and x2 = 500, the query turns into...
SELECT items FROM RSSItem items
WHERE items.id <= 1
AND items.id >= 500
Since no id's are less or equal to 1 and greater or equal to 500 at the same time, the query will give no hits. What you want is probably;
String query =
"SELECT items FROM RSSItem items "
+ "WHERE items.id >= :x1 AND "
+ "items.id <= :x2";
...which with your example data will find all id's between 1 and 500, inclusive.

LINQ Group by and Sum syntax

i have the following vb.net LINQ Query
Dim q = From row In dx.AsEnumerable
Group row By G = New With {.Cat = row.Field(Of Integer)("catalogid")}.Cat,
New With {.Backorder = row.Field(Of Integer)("backorder")}.Backorder Into pg = Group
Select New With
{
.Cat = pg.Cat,
.Backorder = pg.Sum(Function(x) x.Backorder)
}
i have this datatable called dx
catalogid backorder
1 5
1 10
2 1
2 5
i want to Sum backorder column where catalogid is the same so the result is the following
catalogid backorder
1 15
2 6
in the Select new with part, what is wrong?
Try following...
var result = dx.AsEnumerable()
.GroupBy(row => row.Field<int>("catalogid"))
.Select(group => group.Sum(item => item.Field<int> ("backorder")).CopyToDataTable();
or
var result= from s in dx.AsEnumerable()
group s by s.Field<int>("catalogid") into grp
select new {
CatalogId= grp.Key,
Back Order = grp.Sum(r => r.Field<int>("backorder"))
};
DataTable datatbl = result.CopyToDataTable();