Different dates in directory - c#

If have a directory with files that are created on different dates. I want to get the dates.
Is it possible to do this with a linq query, or must I first read all the files and use a foreach loop to get the dates.
Example:
List =
File_1 6/03/2016
File_2 6/03/2016
File_3 6/03/2016
File_4 6/03/2016
File_5 15/04/2016
File_6 21/04/2016
File_7 21/04/2016
File_8 21/04/2016
Result =
6/03/2016
15/04/2016
21/04/2016
Thanks

Based on the comment from #MatthewWatson.
I have make following linq statement
var dateInfo = Directory.EnumerateFiles(Dir).Select(filename => new FileInfo(filename)).Select(i => new { i.LastWriteTime }).GroupBy(g => g.LastWriteTime.Date);
That way I get all the different dates used in my directory.

Clearly you can't process the list of dates without iterating it, but you can use Linq to produce the sequence in the first place, like so:
var dateInfo =
Directory.EnumerateFiles(directoryName)
.Select(filename => new FileInfo(filename))
.Select(info => new {info.Name, info.CreationTime});
That'll give you a list of FullName/CreationTime pairs, where FullName is the full path of the file, and CreationTime is the creation time of the file.
You can process it like so:
foreach (var item in dateInfo)
Console.WriteLine($"{item.FullName} created on {item.CreationTime}");
If you just want the (unique) dates that the files were created on:
var uniqueDates = dateInfo.GroupBy(x => x.CreationTime.Date).Select(y => y.Key);
foreach (var date in uniqueDates)
Console.WriteLine(date);
Finally, if you need the dates to be ordered:
var uniqueDates =
dateInfo.GroupBy(x => x.CreationTime.Date)
.Select(y => y.Key)
.OrderBy(z => z);
(And use .OrderByDescending() for the reverse order, of course.)
If you prefer Linq query syntax:
var uniqueDates =
from date in dateInfo
group date by date.CreationTime.Date into g
orderby g.Key
select g.Key;
Or putting the entire thing in one Linq query (maybe getting a bit unreadble here, so you might want keep it as separate queries, but this is for completeness):
var uniqueDates =
from date in
from file in Directory.EnumerateFiles(directoryName)
select new FileInfo(file).CreationTime
group date by date.Date into g
orderby g.Key
select g.Key;

Related

Order by user and then select max date

I have this LINQ query:
ArrayList arr = new ArrayList();
var data = conn.SCOT_DADOS.OrderByDescending(x => x.DATE)
.GroupBy(r => r.USER)
.ToList();
foreach (var item in data)
{
var itemdata = item.Where(r => r.DATE == item.Max(s => s.DATE));
var name = svc.GetUserName(itemdata.Select(r => r.USER).First().ToString());
var value = itemdata.Select(r => r.VALUE).First();
var date = itemdata.Select(r => r.DATE).First().ToString("dd/MM/yyyy HH:mm:ss");
arr.Add( new{ NAME = name, DATE = date, VALUE = value} );
}
This code will give me the latest result by DATE for each USER.
But the LINQ query is selecting all data from the user and then I'm getting the latest one in the foreach loop.
Is there any way to get only the last data in the LINQ query, so I don't have to take all the user data every time?
I have tried this:
var data = conn.SCOT_DADOS.OrderByDescending(x => x.DATE)
.GroupBy(r => r.USER)
.First()
.ToList();
And then treated item as an object, instead of running selects on it.
It gave me all the data for an individual user, which isn't what I want.
What can be done?
Edit 1:
I get this error if I try to swap OrderByDescending and GroupBy:
Error CS1061 'IGrouping' does not contain a
definition for 'DATE' and no extension method 'DATE' accepting a first
argument of type 'IGrouping' could be found (are
you missing a using directive or an assembly reference?)
Edit 2:
This is some sample data (the column names are not the same because I translated them for the question):
From the data presented, I'd have the results:
If the combination of the (USER, DATE) pair is unique (which seems to be the case when looking at the sample data), the requirement can be trimmed down to
return each record if there is no other record with the same USER and later DATE
which could be translated to the following LINQ query:
var result = conn.SCOT_DADOS
.Where(r => !conn.SCOT_DADOS.Any(r2 => r2.USER == r.USER && r2.Date > r.Date))
// end of Db Query
.AsEnumerable()
.Select(r => new
{
Name = svc.GetUserName(r.User),
Value = r.Value,
Date = r.Date.ToString("dd/MM/yyyy HH:mm:ss")
}).ToList();
I'm a bit confused but from your attempts with First() think you mean this:
conn.SCOT_DADOS.GroupBy(item => item.User)
.Select(grp => grp.OrderByDescending(i => t.Date).First());
This will retrieve for each User only the latest record of it
The reason only swapping the GroupBy and OrderByDescending isn't enough and that you need the Select is that once you grouped that data your enumerable is IEnumerable<IGrouping<User,YourType>>. Each IGrouping is actually a collection by itself so you need to Select only the 1 item you want from it.
Another way is to replace the Select with:
.SelectMany(grp => grp.OrderByDescending(i => t.Date).Take(1))
IMO the first is cleaner, but the second is in the case you need for each user N first items
On the query above you can also add what you have in the foreach loop:
conn.SCOT_DADOS.GroupBy(item => item.User)
.Select(grp => grp.OrderByDescending(i => t.Date).First())
.AsEnumerable()
.Select(item => new {
Name = svc.GetUserName(item.User),
Value = item.Value,
Date = item.Date.ToString("dd/MM/yyyy HH:mm:ss")
}).ToList();
The use of the AsEnumerable() is to invoke the query to be executed to the database before the last Select() which uses the GetUserName method that will not be known to the Oracle database
IMO representing the DateTime as string is not a good way..
Update - The error you get:
Oracle 11.2.0.3.0 does not support apply
It seems that as for this version of Oracle it does not support GroupBy with Select via linq. See Linq to Entities Group By (OUTER APPLY) “oracle 11.2.0.3.0 does not support apply”.
One answer there recommended to create a view in the database for this and then use linq to select over that view. That is what I'd go for
Try this
conn.SCOT_DADOS.GroupBy(x => x.User).Select(x => new
{
User = x.Key,
Date = list.Where(y => y.User == x.Key).Max(y => y.Date)
});

How to c# List<> order by and Group by according to parameters?

I have a class and its List
abc cs = new abc();
List<abc> Lst_CS = new List<abc>();
and I set some value by HidenField in foreach loop
foreach (blah blah)
{
cs = new abc{
No = VKNT,
GuidID=hdnGuidID.Value.ToString(),
RecID=hdnRecID.Value.ToString(),
Date=HdnDate.Value.ToString()
};
Lst_CS.Add(cs);
}
and finally I get a List_CS and I order by Lst_CS according to Date like this;
IEnumerable<abc> query = Lst_CS.OrderBy(l => l.Date).ToList();
but in extra, I want to group by according to No.
Briefly, I want to order by Date and then group by No on Lst_CS How can I do ?
Thanks for your answer
Well you just just do the ordering then the grouping like so:
Lst_CS.OrderBy(l => l.Date)
.GroupBy(l => l.No)
.ToList();
Each list of items in each group will be ordered by date. The groupings will be in the order that they are found when the entire list is ordered by date.
Also your ForEach can be done in one Linq statement, then combined with the ordering and grouping:
var query = blah.Select(b => new abc{
No = VKNT,
GuidID=hdnGuidID.Value.ToString(),
RecID=hdnRecID.Value.ToString(),
Date=HdnDate.Value.ToString()
})
.OrderBy(l => l.Date)
.GroupBy(l => l.No)
.ToList();

Distinct year-months with Linq (to entities)

I have an entity set of Publications with a ReleaseDate property. I would like to get a List of all distinct year-&-month combos from this set for the purpose of creating a pagination widget.
Preferably, I'd like a list of DateTime values with the day as 1 for each distinct year-month from my publications set:
IEnumerable<DateTime> DistinctYearMonths = from p in context.Publications. .... ?
How can I finish this linq-to-entities query?
IEnumerable<DateTime> DistinctYearMonths = context.Publications
.Select(p => new { p.ReleaseDate.Year, p.ReleaseDate.Month })
.Distinct()
.ToList() // excutes query
.Select(x => new DateTime(x.Year, x.Month, 1)); // copy anonymous objects
// into DateTime in memory
The intermediate step to project into an anonymous type is necessary because you cannot directly project into a DateTime (constructors with parameters are not supported in projections in LINQ to Entities and the Year and Month properties of DateTime are readonly, so you can't set them with initializer syntax (new DateTime { Year = p.ReleaseDate.Year, ... } is not possible)).
Try the following query:
(from p in publications
select new DateTime(p.ReleaseDate.Year, p.ReleaseDate.Month, 1)).Distinct();
Using Group By:
(from i in context.Publications
group i by new { i.ReleaseDate.Year, i.ReleaseDate.Month } into g
select g.Key).ToList().Select(i => new DateTime(i.Year, i.Month, 1));
var DistinctYearMonths = context.Publications
.Select(x => new DateTime(x.ReleaseDate.Year, x.ReleaseDate.Month, 1))
.Distinct()
.ToList()
I like chained linq methods much better than the long form. They're much easier to read IMO.
var DistinctYearMonths = (from p in context.Publications
select new DateTime(p.ReleaseDate.Year,
p.ReleaseDate.Month,
1)).Distinct();

how to get items between the search parameters

Work on C#.I have a list named as InputList .From this list I have to search Some string.After search I want to select all item between the search parameter.Bellow picture discribe in detail.
Text Input File:
Collection :
After read the textFile I store data in dataset then,convert the dataset as collection .From this collection i want to get valuse between the search parameters.
I write the bellow syntax but r3 result can not satisfy me.
var InputList = (from p in ds.Tables["InputFile"].Rows.Cast<DataRow>().ToArray() select p.ItemArray).ToList();
var r3 = (from c in InputList
where c.Any(e => e.ToString().Contains("Loading"))
select c).ToList();
If have any query plz ask.Thanks in advance.
To get the results between queries, the SkipWhile() and TakeWhile() would work (both have variants that give the index to the predicate), but I don't think that is quite what you want given your image.
var loadingIndexes = InputList.Select((r, i) => new { Row=row, Index=i })
.Where(x => x.Row.Any(e =>
e.ToString().Contains("Loading"))
.Select(x => x.Index);
var betweenLines = loadingIndexes
.Select(i => InputList
.Skip(i)
.TakeWhile(r => !r.Any(e =>
e.ToString().Contains("FULL")))
.ToList())
.ToList();
Here betweenLines is a List of Lists of DataRows, where each list is between a DataRow containing the string "Loading" (inclusive) and the next `DataRow" containing the string "FULL" (exclusive).

Need lambda expression OrderBy with DateTime conversion

I am trying to create a lambda expression (Linq, C# 3.5) that can perform a OrderBy on a value that is of data type String but which actually contains a parse-able DateTime.
For example, typical values may be "5/12/2009" , "1/14/2008", etc.
The OrderBy clause below works correctly for ordering (as if string data), but I actually want to treat the values as DateTimes, and perform the sort by Date. (The sortColumn would be something like "dateCreated".)
List<MyObject> orderedList = unorderedList.OrderBy(p => p.Details.Find(s => s.Name == sortColumn).Value).ToList();
Is there a way to convert the values in the predicate to do this? Any help appreciated!
Rather gross and inefficient:
List<MyObject> orderedList = unorderedList.OrderBy(p => DateTime.Parse(p.Details.Find(s => s.Name == sortColumn).Value)).ToList();
To reduce the number of lookups/parsing:
List<MyObject> orderedList =
(from extracted in (from p in unorderedList
select new { Item = p, Date = DateTime.Parse(p.Details.Find(s => s.Name == sortColumn).Value })
orderby extracted.Date
select extracted.Item)
.ToList();
Project the date/time value and then sort by it.
var orderedList =
(from p in unorderedList
let value = DateTime.Parse(p.Details.Find(s => s.Name == sortColumn).Value)
orderby value
select p)
.ToList();

Categories