Linq OrderBy - Get Name By ID - c#

I am trying to Sort a List by it's names, but I don't know how to do it when i just have got a ID. Example:
public class CustomTask {
int categoryid;
}
public class DataOption {
int id;
string name;
}
public void Sort() {
List<DataOption> TheListContainingTheCategories = ...;
// The List containing my CustomTasks
List<CustomTask> listTempTasks = ...
var listTasksSorted = listTempTasks.OrderBy(...).ToList();
}
Sorting the IDs is not really hard, but how do i do that when i want to sort it by the names?
Thanks for your help

Guess the shortest way to do this is
var listTasksSorted = from ct in listTempTasks
join d in TheListContainingTheCategories on ct.categoryid equals d.id
orderby d.name
select new {ct, d};
then listTasksSorted looks like this
So The list is ordered by Name and the id's are together and no need of extra functions or members
An Alternative would be
var listTasksSortedAlternative = TheListContainingTheCategories.Where(d =>
listTempTasks.Any(ct =>
d.id == ct.categoryid)).OrderBy(d => d.name);
Which would look like

Try this:
public void Sort()
{
List<DataOption> TheListContainingTheCategories = ...;
Dictionary<int, string> lookup = TheListContainingTheCategories.ToDictionary(x => x.id, x => x.name);
List<CustomTask> listTempTasks = new List<CustomTask>();
var listTasksSorted = listTempTasks.OrderBy(c => lookup[c.categoryid]).ToList();
}
given that you want to sort by the matching
DataOption.name when DataOption.id == CustomTask.categoryId

Related

Linq group by multiple elements and get the count

I have the following json file:
[{"fruits": ["strawberry"]}, {"fruits": ["mango"]}, {"fruits": ["strawberry", "kiwi"]}]
I have the following class
class shake
{
public List<string> fruits = new List<string>();
}
I know this will give me all unique fruits:
var fruits = JsonConvert.DeserializeObject<List<shake>>(json);
var shakes = fruits
.GroupBy(t => t.fruits[0])
.Select(group => new
{
fruit = group.Key,
Count = group.Count()
})
.OrderByDescending(x => x.Count);
I'm trying to get a sorted list with the most popular fruits.
Is it possible to group by multiple elements and get the frequency? is possible to do it with linq?
I think in your example, you are missing the kiwi. I think what you are after is the SelectMany function in Linq.
public class Shake
{
public List<string> Fruits = new List<string>();
}
var list =
(
from shake in shakes
from fruit in shake.Fruits
group fruit by fruit into fruitGroup
let category = new { Fruit = fruitGroup.Key, Count = fruitGroup.Count() }
orderby category.Count descending
select category
).ToList();
I am not sure exactly what final result you are looking for. How close is this?
class Shake
{
public List<string> fruits = new List<string>();
}
static void Main(string[] args)
{
string json = "[{\"fruits\": [\"strawberry\"]}, {\"fruits\": [\"mango\"]}, {\"fruits\": [\"strawberry\", \"kiwi\"]}]";
List<Shake> fruitList = JsonConvert.DeserializeObject<List<Shake>>(json);
var shakes = fruitList.SelectMany(x => x.fruits)
.GroupBy(t => t)
.Select(group => new
{
fruit = group.Key,
Count = group.Count()
})
.OrderByDescending(x => x.Count).ToList();
Console.WriteLine(JsonConvert.SerializeObject(shakes));
}
The output is:
[{"fruit":"strawberry","Count":2},{"fruit":"mango","Count":1},{"fruit":"kiwi","Count":1}]
fruits.SelectMany(x=>x.fruits).GroupBy(x=>x).OrderByDescending(x=>x.Count()).ToDictionary(x=>x.Key, x=>x.Count())
here we on the output get the dictionary where key is name of fruit and value is the count

display two table data at a time in linq

I want to to display two tables information at a time.
List<int> order_track = db.Order_Trackings.Where(e => e.UID == id).Select(q => q.ID).ToList();
if (order_track == null)
{
var rate = db.Ratings.OrderByDescending(e => e.Rate).Take(5);
}
List<int> fidList = db.OrderFoods.Where(q => order_track.Contains(q.OID)).Select(q => q.FID).ToList();
var qs = (from x in fidList
group x by x into g
let count = g.Count()
orderby count descending
select new { KEY = g.Key });
if (order_track.Count == 2)
{
var one = qs;
List<int> idList = new List<int>();
foreach (var val in one)
{
idList.Add(val.KEY);
}
var food = db.Foods.Where(q => idList.Contains(q.ID));
var rate = db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault();
return Request.CreateResponse(HttpStatusCode.OK, rate);
I want to do something like this I hope you will understand what i am trying to achieve Thanks in advance.
var food = db.Foods.Where(q => idList.Contains(q.ID)&&db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault());
return Request.CreateResponse(HttpStatusCode.OK, rate);
If you want to combine the two results into one variable, then the easiest way to do so is by creating an anonymous object, like this:
var result = new
{
food = db.Foods.Where(q => idList.Contains(q.ID)),
rate = db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault()
};
return Request.CreateResponse(HttpStatusCode.OK, result);
You could also create a class with two properties and then create an instance of that class, but if this is the only place where you would use that class then I wouldn't bother doing that.

Group by two columns and do a ToDictionary with a Tuple as Key C# Linq

I have a piece of code where I want to group by two fields and do a ToDictionary on it with the two field as a tuple key. I am not sure of the syntax. Following is what I have, But the problem is it creates a Tuple with single item.
var count = this.Db.Query<EmployeeCount>(#"select
employername, ein, month, headcount
from employerInfo A inner join MonthlyInfo B on (A.Id = B.Id)
where A.ClientId = #Client",
new { run.Client })
.GroupBy(r => new { r.EIN, r.EmployerName})
.ToDictionary(pair => Tuple.Create<string>(pair.Key.ToString()), pair => pair.ToDictionary(r => (Months)r.month, r => r.headcount));
And my EmployeeCount class is
private class CountQuery
{
public string EmployerName;
public string EIN;
public int Month;
public int HeadCount;
}
I try to do a Tuple.Create, but i am not sure how to notify that the params would be EIN and Employername for the Tuple.
I figured it out myself as below
var count = this.Db.Query<EmployeeCount>(#"select
employername, ein, month, headcount
from employerInfo A inner join MonthlyInfo B on (A.Id = B.Id)
where A.ClientId = #Client",
new { run.Client })
.GroupBy(r => new { r.EIN, r.EmployerName}).ToDictionary(pair => Tuple.Create<string,string>(pair.Key.EIN.ToString(),pair.Key.EmployerName), pair => pair.ToDictionary(r => (Months)r.ReportingMonth, r => r.FTECount))

Applying multiple group functions on IQueryable<T>

Given the following simple object
public class Foo {
public int PrimaryKey;
public int ForeignKey;
public bool FlagOne;
public bool FlagTwo;
}
Suppose I have received a IQueryable<Foo>. Generally, if I want to do a count operation on each flag I would do this:
IQueryable<Foo> foos = GetFoos();
var total = foos.Count();
var flagOneTotal = foos.Count(p => p.FlagOne);
var flagTwoTotal = foos.Count(p => p.FlagTwo);
In EF, the above would execute 3 queries in the database. I would like to retrieve all these in a single query.
For grouping, I can do this to execute single query:
var q = from foo in foos
group foo by foo.ForeignKey into g
select new {
ForeignKey = g.Key,
Total = g.Count(),
FlagOneTotal = g.Count(p => p.FlagOne),
FlagTwoTotal = g.Count(p => p.FlagTwo)
};
var list = q.ToList();
But how would I do the same if I want to get the totals for all elements regardless of foreign key in a single query and a single anonymous object ?
In other words, how would I tell .net that all elements in foos need to be considered 1 group so I can do Count operations on them.
This should do the job:
var q = from foo in foos
group foo by 1 into g
select new {
Total = g.Count(),
FlagOneTotal = g.Count(p => p.FlagOne),
FlagTwoTotal = g.Count(p => p.FlagTwo)
};
var list = q.ToList();
Cheers

how to convert List<SomeType> to List<AnotherType>?

I have two data types:
class MyDataType {
public int Id;
private int Field;
public String AnotherFieldOrProperty;
// + there are some methods
}
class MyDataTypeDescriptor {
public int Id;
public String Description;
}
I need to convert List<MyDataType> to List<MyDataTypeDescriptor> such a way:
MyDataTypeDescriptor.Id = MyDataType.Id
MyDataTypeDescriptor.Description = MyDataType.ToString();
I guess C# can do that very easy and fast in just one line of code, but I don't know how because I'm not familar with such advanced techniques. Would someone help me please?
Thanks
This should do it (where myDataTypes is your List<MyDataType>):
List<MyDataTypeDescriptor> myDataTypeDescriptors =
myDataTypes.Select(x => new MyDataTypeDescriptor
{
Id = x.Id,
Description = x.ToString()
}).ToList();
(from i in list1
select new MyDataTypeDescriptor { Id = i.Id, Description = i.ToString()).ToList();
You can use automapper to do this automagically for you if you don't want to write the iterator yourself..
You can do it by using LINQ Select method:
List<MyDataType> list;
// Process list...
List<MyDataTypeDescriptor> result =
list.Select(x => new MyDataTypeDescriptor() { Id = x.Id, Description = x.ToString() }).
ToList<MyDataTypeDescriptor>();
Or if you have a constructor for MyDataTypeDescriptor that takes an Id and a Description:
List<MyDataType> list;
// Process list...
List<MyDataTypeDescriptor> result =
list.Select(x => new MyDataTypeDescriptor(x.Id, x.ToString())).
ToList<MyDataTypeDescriptor>();
For simple conversions, you can use the Select method like this:
List<int> lstA = new List<int>();
List<string> lstB = lstA.Select(x => x.ToString()).ToList();
For more compex conversions, you the ConvertAll function, like this:
List<int> lstA = new List<int>();
List<string> lstB = lstA.ConvertAll<string>(new Converter<int, string>(StringToInt));
public static string StringToInt(int value)
{
return value.ToString();
}
You can do this with LINQ:
var listofMyDataTypeDescriptor = (from m in listOfMyDataType
select new MyDataTypeDescriptor()
{
Id = m.Id,
Description = m.ToString()
}).ToList();
You can't actually convert them, you'll have to iterate through the collection and create a new Descriptor for each DataType
var result = (from MyDataType m in listOfMyDataType select new MyDataTypeDescriptor
{
Id = m.Id,
Description = m.toString(),
}).ToList();
Just to add one more way
define an explicit user type conversion
MSDN
then do
var newlist = MyDataTypleList.Cast<MyDataTypeDescriptor>().ToList();

Categories