orderByDescending date, month and year - c#

I am using a LINQ query to get the data order by descending date. but when the year is changed then descending order of date is not in the proper way
Here is my code
In this code, LastLogin is a column with DateTime datatype. I have to sort data by this column name.
var res = objUI.Where(x => x.LastLogin != null)
.GroupBy(x => x.LastLogin.Value.Date)
.Select(x => new { LastLogin = string.Format("{0:MM/dd/yyyy}", x.Key) })
.OrderByDescending(x => x.LastLogin)
.ToList();

You shouldn't to try order the date as string;
var res = objUI.Where(x => x.LastLogin != null)
.GroupBy(x => x.LastLogin.Value.Date)
.OrderByDescending(x => x.Key)
.Select(x => new { LastLogin = string.Format("{0:MM/dd/yyyy}", x.Key) })
.ToList();

You're ordering by your string representation which starts with the month.
It looks like you're actually only interested in distinct dates though - grouping and then discarding everything other than the key is equivalent to just projecting and then taking distinct data. I'd also suggest avoiding an anonymous type unless you really need it - an anonymous type with only a single property is usually a bad idea.
Finally, if you're formatting a single value - certainly a DateTime value - it's simpler to just call the ToString method. In the code below I've explicitly specified the invariant culture too - otherwise you may find an unexpected calendar system is used...
So I'd write:
var res = objUI.Where(x => x.LastLogin != null)
.Select(x => x.LastLogin)
.Distinct()
.OrderByDescending(x => x)
.Select(x => x.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture))
.ToList();

Related

LINQ groupby search in contains

I have the following result:
var result = (from p1 in db.Table
select new ReportInform
{
DataValue = p1.DataValue,
SampleDate = p1.SampleDate
})
.Distinct()
.ToList();
// Next getting list of duplicate SampleDates
var duplicates = result.GroupBy(x => x.SampleDate)
.Where(g => g.Count() > 1)
.Select (x => x)
.ToList();
foreach (var r in result)
{
if (duplicates.Contains(r.SampleDate)) // get error here on incompatbility
{
r.SampleDate = r.SampleDate.Value.AddMilliseconds(index++);
}
}
Cannot convert from 'System.DateTime?' to 'System.Linq.IGrouping
That error is pretty clear but may not be at a first glance. As a programmer, you need to learn how to read, understand and make sense of compiler or runtime errors.
Anyhow it is complaining that it cannot convert DateTime? to System.Linq.IGrouping<System.DateTime, ReportInForm>. Why? Because this query returns an System.Linq.IGrouping<System.DateTime, ReportInForm>
var duplicates = result.GroupBy(x => x.SampleDate)
.Where(g => g.Count() > 1)
.Select (x => x)
.ToList();
The GroupBy method returns IGrouping<System.DateTime, ReportInForm> which has a Key and the Key is the thing you grouped by and a list of items in that group. You are grouping by SampleDate and checking if there are more than one items in that group and then selecting the group. Thus dulplicates has a list of IGrouping<System.DateTime, ReportInForm> and you are asking the runtime to check if it contains a DateTime? and it blows up at this line:
duplicates.Contains(r.SampleDate)
One way to fix this is: What you want to do is to select the key of that group. Thus do this:
.Select (x => x.Key)
If you are expecting duplicates to be of type List<DateTime?> then you meant to write this
.Select(x => x.Key)
instead of
.Select(x => x)

Return a List of distinct values from DataGridView

As the topic says: Is there a way to return a list of distinct values from a certain Column of a DataGridView?
This should do what you asked for:
var vv = dataGridView1.Rows.Cast<DataGridViewRow>()
.Select(x => x.Cells[yourColumn].Value.ToString())
.Distinct()
.ToList();
Note that the simple version above assumes that there are only valid values. If you also may have new rows or empty cells you may want to expanded it like this:
var vv = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(x => !x.IsNewRow) // either..
.Where(x => x.Cells[column].Value != null) //..or or both
.Select(x => x.Cells[column].Value.ToString())
.Distinct()
.ToList();

Difficulty with LINQ Query writing custom sort logic

I have files like Avinash_Create.sql, Avinash_Insert.sql, Avinash_Update.sql , Avinash_Delete.sql.
I need to iterate over the files list and group them based on the name and order by create, insert, update, and delete files.
I am finding it difficult difficult to accomplish. This is what I have so far:
var userGroups = shortfilenames.GroupBy(s => s.Substring(0, s.IndexOf('_')))
.Select(g => g.OrderBy(x => x.Substring(x.IndexOf('_')).Contains("CREATE"))
.ThenBy(x => x.Substring(x.IndexOf('_')).Contains("INSERT"))
.ThenBy(x => x.Substring(x.IndexOf('_')).Contains("UPDATE"))
.ThenBy(x => x.Substring(x.IndexOf('_')).Contains("DELETE")));
The above query is grouping by name 'Avinash' but not working for custom ordering. Please help.
Update:
Please see updated query , still it is not sorting properly
Uses Split to extract the relevant sections of the string. Converts the result to upper case, which seems to be missing from your attempt. Additionally makes it a bit shorter by using an array to hold your custom sort order and then Array.IndexOf to get a sort order from it, rather than multiple OrderBy/ThenBy.
var ordering = new [] {"CREATE", "INSERT", "UPDATE", "DELETE"};
var results = shortfilenames.GroupBy(s => s.Split('_')[0])
.Select(g => g.OrderBy(x => Array.IndexOf(ordering, x.Split('_')[1].Split('.')[0].ToUpper())));
This seems to be what what you want:
var shortfilenames = new List<string>(){"Avinash_Create.sql" , "Avinash_Insert.sql" , "Avinash_Update.sql" , "Avinash_Delete.sql"};
var userGroups = shortfilenames
.Select(fn =>
{
string fileName = Path.GetFileNameWithoutExtension(fn);
string[] nameAndAction = fileName.Split('_');
return new
{
extension = Path.GetExtension(fn),
fileName,
name = nameAndAction[0],
action = nameAndAction[1]
};
})
.GroupBy(x => x.name)
.Select(g => g.OrderByDescending(x => x.action.Equals("CREATE", StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(x => x.action.Equals("INSERT", StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(x => x.action.Equals("UPDATE", StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(x => x.action.Equals("DELETE", StringComparison.InvariantCultureIgnoreCase))
.ToList());
foreach (var ug in userGroups)
foreach (var x in ug)
Console.WriteLine("{0} {1}", x.name, x.action);
prints out:
Avinash Create
Avinash Insert
Avinash Update
Avinash Delete
Presumes that the file-names always contain the underscore.

Getting Rounded Values in the final result of Linq Query

How can the below linq Query be modified such that i can get a Rounded figure of values.
var result=GetStudentsWithTheirMarks()
.OrderByDescending(x => Math.Round(x.PercentageScore)).Take(5)
.OrderBy(x => x.PercentageScore);
Please ignore the presence of two order by clause as this is done for with a purpose.
GetStudentsWithThierMarks returns Student List with their FirstName and PercentageScore.
I believe in the above query Math.Round is only applicable when during order by operation so final result still contains values in decimal places whereas i am only interested to see rounded figures with integer values. I just cant figure out the syntax.
You just need a Select :
var result= GetStudentsWithTheirMarks()
.OrderByDescending(x => Math.Round(x.PercentageScore))
.Take(5)
.OrderBy(x => x.PercentageScore)
.Select(x => Math.Round(x.PercentageScore));
You can store this value in an anonymous type:
var result = GetStudentsWithTheirMarks()
.Select(s => new
{
Student = s,
RoundedPercentageScore = Math.Round(s.PercentageScore)
})
.OrderByDescending(x => x.RoundedPercentageScore )
.Take(5)
.OrderBy(x => x.Student.PercentageScore);
Now you can access it in this way:
foreach(var x in result)
Console.WriteLine("RoundedPercentageScore: " x.RoundedPercentageScore);

Linq to Sql - DateTime Format - YYYY-MMM (2009-Mar)

I want to write a Linq to Sql query that does a count and groups by a Username and DateTime. I want the DateTime to be formatted like following "YYYY-MMM" (i.e. 2009-Mar).
I thought this would work but Linq to Sql can't parse the ToString "format" argument.
dc.MyTable
.GroupBy(r => new
{
Name = r.UserName,
YearMonth = r.SomeDateTime.ToString("yyyy-MMM")
})
.Select(r => new
{
Name = r.UserName,
YearMonth = r.YearMonth,
Count = r.Count()
})
.OrderBy(r => r.YearMonth)
.ThenBy(r => r.Name);
Does anyone have any thoughts/suggestions?
Thanks.
I wonder if you shouldn't do that the "long" way...
dc.MyTable
.GroupBy(r => new
{
Name = r.UserName,
Year = r.SomeDateTime.Year,
Month = r.SomeDateTime.Month
})
.Select(r => new
{
Name = r.UserName,
Year = r.Year,
Month = r.Month,
Count = r.Count()
})
.OrderBy(r => r.Year)
.ThenBy(r => r.Month)
.ThenBy(r => r.Name);
If you need the format as a string, do that later at the UI. Either by reconstructing a DateTime etc, or using CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(...).
I would avoid turning anything into a string at the database. Group by r.SomeDateTime.Year and r.SomeDateTime.Month, ordering by year then month then name, select the year and the month separately (along with the count), and then if you need to do the projection to a string format back in the client code.
By the way, I suspect your second OrderBy should be a ThenBy - currently the Name is actually the most important thing you're ordering by.

Categories