I have a list like the following one:
|Name|Val. Date 1| Val. Date 2|
|PA | 200| 200|
|PB | 0| 300|
|PC | 200| 0|
|PD | 150| 150|
Ordering the list by Val. Date1 will give me something like: PA, PC, PD and PB. and something similar if I do it for Val. Date 2.
But what I really need to do, is to order it by the highest value recorded in Date 1 or Date 2, what results in something like this: PB, PA, PC and PD.
How can I solve this matter?
use Math.Max() to get the maximum value and then order by it:
list.OrderByDescending(x => Math.Max(x.Date1, x.Date2));
Since you are using a list, you can do an inline sort of the list using List.Sort(Comparison<T>):
list.Sort((lhs, rhs) =>
(
Math.Max(lhs.Val.Date1, lhs.Val.Date2) -
Math.Max(rhs.Val.Date1, rhs.Val.Date2)
));
If you are assigning the results of the Linq solution back to a list using .ToList(), then doing an in-place sort instead will be much more efficient with one important caveat:
List.Sort() is NOT a stable sort, so that it doesn't preserve the ordering of equal values. The Linq OrderBy, however, is a stable sort.
Another way is to use something like:
var sortedList = ListOfData.OrderByDescending(x=>x.Val1).ThenByDescending(x=>x.Val2);
See:
Multiple “order by” in LINQ
Ordering data in LINQ queries by more than one column
Multiple Field Sorting by Field Names Using Linq
Related
We have data as follows
Created On
Supplier
01-Nov-21
ABC
02-Nov-21
XYZ
15-Nov-21
ABC
20-Nov-21
MNO
25-Nov-21
ABC
So we want to record in descending order of creation but 1st want all "ABC" records on the top.
I tried with this one, but didn't worked.
object.OrderByDescending(m => m.name== "ABC").ThenBy(x => x.CreatedOn)
So instead of getting records as follows
01-Nov-21 | ABC
15-Nov-21 | ABC
25-Nov-21 | ABC
02-Nov-21 | XYZ
20-Nov-21 | MNO
It was coming in same order as above i.e. based on createdOn field
Am i missing anything here?
in descending order of creation but 1st want all "ABC" records on the top
You need to use ThenByDescending - using OrderByDescending initially doesn't then set the sorting of the date up to be descending too
I don't personally think you should sort a bool in your first clause, because it's not obvious to everyone how booleans sort. Rather than it be something one has to remember/look up, I would recommend that you use the bool to generate an int for sorting because everyone can easily understand your intent (everyone can put 0 and 1 into ascending order):
foreach(var x in list.OrderBy(m => m.name == "ABC" ? 0 : 1).ThenByDescending(x => x.CreatedOn))
//process your objects in turn here
To achieve a "date descending but all ABC on top" you first sort on whether something is ABC or not (and bear in mind that that's an exact, case sensitive match, unless this query is being translated to SQL and send to a DB like SQL server, where case sensitivity depends on the collation of the column being sorted/where trailing spaces may be ignored), then you want to sort the date descending with ThenByDescending.
I have a feature class which contain property information, what I would like to do it total the value of all properties and display that in a table. The attribute table looks something like this:
ObjectId PID Value
0 1000 10,000
1 1001 25,000
2 1002 100,000
I would like to sum the value field, in order to give me a total for the entire area. So in this example, the value of all properties would be $135,000... I would like to calculate this and display it...
sounds like a pretty straight forward problem, but I can't seem to find a solution. How to do this on Xamarin forms MVVM format
Well, assuming you are using SQL then you would use something like:
select sum(count) from TableXXX where location = 'colombo'.
If you are using EF then it would be more like:
double x = dbContext.DbSet("XXX")
.Where(item => item.Location == "colombo")
.Select(item => item.Count)
.Sum();
I have an already sorted list of object (sorted by date)
public class HistoryValue{
public DateTime Date {get;set;}
public decimal Value {get;set;
}
Then I have a list of days, for example,
1MonthAgo, 2MonthAgo,3MonthAgo,120MonthAgo
What I need is to find the Value on date
1MonthAgo, 2MonthAgo,3MonthAgo,120MonthAgo
If the date can not be found in the list, I should return the one just before that date. It is easiest to explain in a SQL statement although I am doing the real work in c#:
select top 1 Value
from HistoryValueList
where Date between #d12m-#lookbackdaymax and #d12m order by Date desc
I was thinking of using binary search, but don't think binary search will do exactly what I want. Maybe it is best do a looping and remember the closet object of each?
What you want is a "lower bound" kind of algorithm (please check this question), that is, a binary search (or bisect) algorithm that finds the left most element less than or equal to your search element.
You're in luck, there is such a thing called Language Integrated Query (LINQ) which lets you run queries on objects in C# which implement IEnumerable. That includes the List<HistoryValue> you're using.
You're looking for some code like:
HistoryValue val = historyValues.FirstOrDefault(v => v.Date > dateMin && v.Date <= dateMax);
Where historyValues is your list object.
This is pretty easy in C#. I am supposing that you get all records in list of HistoryValue class from DB!
Then you will write code like this:
List<HistoryValue> list = list; //your list get from db here!
HistoryValue historyValue = list.Where(m=>m.Date >= #12m && m.Date <= #lookbackdaymax ).First();
I have a list that I need sorted by two fields. I'm looking for the list to be sorted by the first field and then, if there are any null in the first field, to sort by the second field.
I have two field for example Distance and from time and I want a sorted list with both fields. But I want to give priority to from time and then distance so how can I sort the list using Linq?
You can use many orderBy closes like this:
from user in users
orderby user.Name, user.Age, user.Name.Length
select user;
Or you can do something like this:
OrderBy(<sort 1>).ThenBy(<sort 2>)
I need this function for a transaction table. My datatables looks like this.
RecordsInDatabase-Table
a_code | b_code
AB | 001
AB | 002
AC | 001
RecordsInTextFile-Table
a_code | b_code
AB | 002
AC | 005
AC | 009
I need to compare using two IDs, a_code and b_code.
Therefore, if I run the LINQ code (or other), a datable would contain records that are IN the database, but NOT in the text file.
RecordsNotInTextFile-Table
a_code | b_code
AB | 001
AC | 001
I already have a LINQ code, but it only compares using one ID.
DataTable affixesInDatabase = affixDAO.SelectAllAffix();
IEnumerable<string> affixesNotInTextFile = affixesInDatabase.AsEnumerable().Select(r => r.Field<string>("affix_code"))
.Except(affixesInTextFile.AsEnumerable().Select(r => r.Field<string>("affix_code")));
if (affixesNotInTextFile.Any())
{
DataTable affixesToBeDeleted = (from row in affixesInDatabase.AsEnumerable()
join id in affixesNotInTextFile
on row.Field<string>("affix_code") equals id
select row).CopyToDataTable();
foreach (DataRow dr in affixesToBeDeleted.Rows)
{
affixDAO.DeleteAffix(dr[0].ToString());
}
}
return "Affix data successfully edited.";
If you need to filter out two exceptions, the simplest way to do it would be to chain two .Except() calls into your LINQ expression.
From your comment, it appears that you aren't familiar with the principles on which LINQ operates. If you want to understand, I'd suggest reading Jon Skeet's "Edulinq" series, in which he re-implements the standard LINQ query operators and explains how it all works as he goes. But here's the short version:
LINQ is a set of extension methods that operate on enumerable sequences (ie. IEnumerable<T>). Each method takes a sequence as input and applies some operation, and the majority of them produce a new sequence as output. (There are some that produce a single value instead, but not the ones we're dealing with.) So here's what your query is doing:
IEnumerable<string> affixesNotInTextFile = //assignment. You know how that works
affixesInDatabase //our base sequence that we're starting from
.AsEnumerable() //ensure that we're working with an IEnumerable, not an IQueryable
.Select() //transform the sequence from the original objects to a sequence of Field<string> values from the original objects
.Except() //filter out of the transformed sequence anything that's in *this* sequence
Except() produces a new sequence, and so you can chain another .Except() on the end of the expression that will filter the sequence further. Read the Edulinq posts, and pay particular attention to the ones on Select and Except, and you should come out of it understanding how LINQ works well enough to accomplish what you need.