extract file content greater than datetime.now - c#

I have a file with content like below,
2018-02-28 10:00:00,A1, A2
2018-02-28 10:05:00,A3, A4
2018-02-28 10:10:00,A5, A6
2018-02-28 10:00:00,A7, A8
Now I would like get all the file content (as a different file) from date/time greater than 2018-02-28 10:05:00?
I am able to check modified files after certain data,
var files = directory.GetFiles().Where(file=>file.LastWriteTime >= datetine.now);
But how to get content ?

You can use this (using C#7 out variable feature):
var fileContents = directory.GetFiles()
.Select(f => new
{
File = f,
Content = File.ReadLines(f.FullName)
.Select(l => new{ Line = l, Fields = l.Split(',') })
.Select(x => new
{
x.Line, x.Fields,
DateStr = x.Fields[0].Trim(),
IsValid = DateTime.TryParse(x.Fields[0].Trim(), out var date),
Date = date
})
.Where(x => x.IsValid && x.Date > DateTime.Now)
.ToArray()
});

Try following
string input = "2018-02-28 10:00:00,A1, A2\n" +
"2018-02-28 10:05:00,A3, A4\n" +
"2018-02-28 10:10:00,A5, A6\n" +
"2018-02-28 10:00:00,A7, A8";
DateTime now = DateTime.Now;
var results = input.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Split(new string[] {","}, StringSplitOptions.RemoveEmptyEntries))
.Select( y => new { date = DateTime.Parse(y.First()), colA = y.Skip(1).First(), colB = y.Last() })
.Where(x => x.date <= now).ToList();

Related

How to get pair value from CultureTypes object in C#?

I have created single object of IEnumerable
want to make it dictionary type object to handle key and value.
want to extract Currency Symbol and Name from the Cultures.
IEnumerable<string> currencySymbols = CultureInfo.GetCultures(CultureTypes.SpecificCultures) //Only specific cultures contain region information
.Select(x => (new RegionInfo(x.LCID)).ISOCurrencySymbol )
.Distinct()
.OrderBy(x => x);
foreach(string s in currencySymbols)
{
CurrencyTable tbl = new CurrencyTable();
tbl.Iso = s;
tbl.Name = s;
}
I want like below
IEnumerable<string,string>
How it possible?
CurrencyTable is a class that contains ID | Iso | Name Filed
this one returns all currencySymbols with its first distinct english currency name
var currencySymbols =
CultureInfo.GetCultures(CultureTypes.SpecificCultures) //Only specific cultures contain region information
.Select(x => new RegionInfo(x.LCID))
.GroupBy(x => x.ISOCurrencySymbol)
.Select(x => new CurrencyTable() {
Iso = x.Key,
Name = x.Select(y => y.CurrencyEnglishName).Distinct().FirstOrDefault()
});
and here goes the LINQ-Version:
var symbols = from x in CultureInfo.GetCultures(CultureTypes.SpecificCultures)
let region = new RegionInfo(x.LCID)
group region by region.ISOCurrencySymbol into g
let names = from r in g select r.CurrencyEnglishName
select new CurrencyTable() {
Iso = g.Key,
Name = names.FirstOrDefault()
};
You can't return IEnumerable<string,string>. But you can return IEnumerable<anonymous tyep>.
For example :
var currencyTables = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
.Select(s => new RegionInfo(s.LCID))
.Select(r => new
{
Iso = r.ISOCurrencySymbol,
Name = r.CurrencyEnglishName
}).GroupBy(s => s.Iso)
.OrderBy(r =>r.Key)
.Select(a => new { Iso = a.Key, Name = a.First().Name });
And you can return IEnumerable<CurrencyTable>.
For example:
var currencyTables = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
.Select(s => new RegionInfo(s.LCID))
.Select(r => new
{
Iso = r.ISOCurrencySymbol,
Name = r.CurrencyEnglishName
}).GroupBy(s => s.Iso)
.OrderBy(r =>r.Key)
.Select(a => new CurrencyTable{ Iso = a.Key, Name = a.FirstOrDefault().Name });

How to display each month, even if no data for this month

The query works fine, except it only pulls the value where a month has more then zero incident, for example if January had no value, then it doesn't show January. I would like to show all months.
var result = tIncidentReportings
.AsEnumerable()
.GroupBy(c => c.Date.ToString("MMM"))
.Select(g => new { Month = g.Key, Count = g.Count() })
.OrderBy(x => DateTime.ParseExact((x.Month).ToString(), "MMM", CultureInfo.InvariantCulture));
The issue is you are going to have missing months for whatever months don't have any reports. You'll have to check to see which months don't have any and add them manually.
var result = tIncidentReportings
.AsEnumerable()
.GroupBy(c => c.Date.ToString("MMM"))
.Select(g => new { Month = g.Key, Count = g.Count() })
.OrderBy(x => DateTime.ParseExact((x.Month).ToString(), "MMM", CultureInfo.InvariantCulture));
var months =
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.MonthGenitiveNames.Select(s => s.Substring(0,3)).ToList();
months.foreach(m => {
if(!results.Select(r => r.Month).Contains(m)){
results.Add(new {Month = m, Count = 0};
});
Something like that
Or a rewrite of:
var months = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.MonthGenitiveNames.Select(s => s.Substring(0,3)).ToList();
var reports = months.Select(m =>
new {
Month = m,
Count = tIncidentReportings.AsEnumerable().Where(i => i.Date.ToString("MMM") == m).Count()
}
).OrderBy(x => DateTime.ParseExact((x.Month).ToString(), "MMM", CultureInfo.InvariantCulture)).ToList();

Linq group by return always values

I have this small code and I wanna return Today and count always with or not values.
DateRange dateRangeLastWeek = DateRange.LastWeek(DateTime.Now);
var caseCounts = db.Find(x => x.FinishDate.HasValue)
.Where(c => c.FinishDate.Value.Date == dateRangeLastWeek.Today.Date ||
(c.FinishDate.Value.Date >= dateRangeLastWeek.Start && c.FinishDate.Value.Date <= dateRangeLastWeek.End))
.GroupBy(c => c.FinishDate.Value.Date == dateRangeLastWeek.Today.Date ? "Today" : "Last Week")
.Select(g => new JsonChartModel
{
Name = g.Key,
Value = g.Count()
});
In this case I wanna return:
Today : 10
Last Week: 0
Not really elegant, but you could use an Union with default Values, and select the max between default and returned values.
var defaultValues = new List<JsonChartModel> {
new JsonChartModel{Name = "Today", Value = 0},
new JsonChartModel{Name = "Last Week", Value = 0}
};
var result = <YourQuery>.ToList().Union(defaultValues)
.GroupBy(m => m.Name)
.Select(g => new JsonChartModel) {
Name = g.Key,
Value = g.Max(x => x.Value)
});

string manipulation to extract substring of particular pattern

I have the following string in c#
Count([AssignedTo]) as [AssignedTo] , Sum([Billing Amount]) as [Billing Amount] , Max([Billing Rate]) as [Billing Rate] , Min([ExecutionDate]) as [ExecutionDate] , Average([HoursSpent]) as [HoursSpent] , [Project], [Sub-Project], [TaskName], [Vendor], [Work Classification], [Work Done], Count([WorkItemType]) as [WorkItemType]
Now I want list of all fields having aggregate function , through string manipulation or linq
output like
Count([AssignedTo])
Sum([Billing Amount])
Max([Billing Rate])
Min([ExecutionDate])
Average([HoursSpent])
Count([WorkItemType])
Perhaps this works for you:
var aggr = new []{ "Count", "Sum", "Max", "Min", "Average"};
var allAggregates = text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(col => new{ col, token = col.TrimStart().Split().First() })
.Where(x => x.token.Contains('(') && aggr.Any(a => x.token.StartsWith(a, StringComparison.OrdinalIgnoreCase)))
.Select(x => x.token);
DEMO
can i get the field name only which is inside function
I prefer string methods instead of regex if possible:
var allAggregates = text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(col => new { col, token = col.TrimStart().Split().First() })
.Where(x => x.token.Contains('(') && aggr.Any(a => x.token.StartsWith(a, StringComparison.OrdinalIgnoreCase)))
.Select(x => {
string innerPart = x.token.Substring(x.token.IndexOf('(') + 1);
int index = innerPart.IndexOf(')');
if (index >= 0)
innerPart = innerPart.Remove(index);
return innerPart;
});
var aggregates = new []{ "Count", "Sum", "Max", "Min", "Average"};
var output=Regex.Matches(input,#"(\w+)\(.*?\)")
.Cast<Match>()
.Where(x=>aggregates.Any(y=>y==x.Groups[1].Value))
.Select(z=>z.Value);
This is another way:
string[] funcNames = new string[]{"Sum","Average","Count","Max","Min"};
string s = "Your String";
var output = from v in s.Split(',')
where funcNames.Contains(v.Split('(')[0].Trim())
select v.Split(new string[]{" as "},
StringSplitOptions.RemoveEmptyEntries)[0].Trim();
.Split('(')[1].Split(')')[0]; //this line is to get only field names
//Print results
foreach(var str in output) Console.WriteLine(str);

Filter data from Xml according to date in C#

I need help filtering xml file according to dates , with this part of the code that i have it only prints out all average information according to user name and place
Runner run = new Runner();
string filePath = "runners.xml"; //path
XDocument xDoc = XDocument.Load(filePath);
string userSelect = name;
var averageAddDistancequery = xDoc.Descendants("User").Where(w => (string)w.Element("Name") == user).Select(s => new
{
add = s.Elements("Attempts").Where(w => (string)w.Element("Place").Value == "Paris").Select(t => t.Element("Distance").Value)
}).ToList();
if (averageAddDistancequery[0].add.Count() > 0)
{
var aa = averageAddDistancequery[0].add.Average(a => float.Parse(a));
run.averageDistance = aa.ToString();
}
else
{
// nothing
}
var averageAdd2Distancequery = xDoc.Descendants("User").Where(w => (string)w.Element("Name") == userSelector).Select(s => new
{
add = s.Elements("Attempts").Where(w => (string)w.Element("Place").Value == "Madrid").Select(t => t.Element("Distance").Value)
}).ToList();
if (averageAdd2Distancequery[0].add.Count() > 0)
{
var aa = averageAdd2DistanceSubquery[0].add.Average(a => float.Parse(a));
run.averageDistance2 = aa.ToString();
}
else
{
// nothing
}
xmlDoc.DocumentElement.SetAttribute("searching", user);
XmlNodeList tests = xmlDoc.SelectNodes("//User[Name =/*/#searching]/Attempts");
listBox1.Items.Clear();
listBox1.Items.Add("Runners Name: " + user);
listBox1.Items.Add("Overall Distance in Paris: " + run.averageAdd);
listBox1.Items.Add("Overall Distance in Madrid: " + run.averageSub);
For example if my xml file looks like this
Users>
<User>
<Name>David</Name>
<Attempts>
<Place>Paris</Place>
<Date>3/29/2012</Date>
<Distance>100</Distance>
</Attempts>
<Attempts>
<Place>Madrid</Place>
<Date>7/28/2012</Date>
<Distance>100</Distance>
</Attempts>
<Attempts>
<Place>Paris</Place>
<Date>8/19/2012</Date>
<Distance>60</Distance>
</Attempts>
<Attempts>
<Place>Madrid</Place>
<Date>9/29/2012</Date>
<Distance>200</Distance>
</Attempts>
</User>
<User>
<Name>Lenny</Name>
<Attempts>
<Place>Paris</Place>
<Date>9/29/2012</Date>
<Distance>130</Distance>
</Attempts>
</User>
</Users>
If i run the code for david it will print out something like this
User:David
Average Distance in Paris:// data
Average Distance in Madrid: // data
This is not what i want, what i want is to select any two dates lets from a textbox and display only the information between those two dates
For example if i chose david, from date 3/29/2012 to 8/29/2012
I would want and output something like this:
User: David
Average Distance in Paris from 3/29/2012 to 8/29/2012: //data
Average Distance in Madrid from 3/29/2012 to 8/29/2012: //data
Ive been trying for hours, i need help implementing this
Use LINQ to XML, assume in here two dates you select from TextBox:
var userElement = xDox.Descendants("User")
.SingleOrDefault(u => u.Element("Name").Value == "David");
if (userElement != null)
{
var result = userElement.Descendants("Attempts")
.Select(a => new
{
Place = a.Element("Place").Value,
Date = DateTime.Parse(a.Element("Date").Value),
Distance = int.Parse(a.Element("Distance").Value)
})
.Where(a => a.Date >= DateTime.Parse("3/29/2012")
&& a.Date <= DateTime.Parse("8/29/2012"))
.GroupBy(a => a.Place)
.Select(g => new {Place = g.Key, Avg = g.Average(x => x.Distance)});
}
You can do, what you need, with Linq to Xml:
XElement x = XElement.Load("In.xml");
IFormatProvider f = new System.Globalization.CultureInfo("en-US");
DateTime bdate = DateTime.Parse("3/29/2012", f);
DateTime edate = DateTime.Parse("8/29/2012", f);
string username = "David";
var info = x.Elements("User")
.Where(u => u.Element("Name").Value == username)
.Select(u => new
{
Name = u.Element("Name").Value, //user name
AverageAttempts = u.Elements("Attempts") //select user's attempts
.Where(a => //filter by dates
{
DateTime d = DateTime.Parse(a.Element("Date").Value, f);
return d >= bdate && d <= edate;
})
.GroupBy(a => a.Element("Place").Value) //group by place
.Select(g => new // create summary info by place
{
Place = g.Key, //place
BeginDate = g.Elements("Date")
.Select(d => DateTime.Parse(d.Value, f))
.Min(), //min date, i.e. first attempt
EndDate = g.Elements("Date")
.Select(d => DateTime.Parse(d.Value, f))
.Max(), //max date, i.e. last attempt
Distance = g.Elements("Distance")//average distance
.Average(d => decimal.Parse(d.Value))
})
})
.FirstOrDefault();
if(info!=null)
{
Console.WriteLine(info.Name);
foreach (var aa in info.AverageAttempts)
{
Console.WriteLine(string.Format("{0} [{1} - {2}]:\t{3}",
aa.Place,
aa.BeginDate,
aa.EndDate,
aa.Distance));
}
}
The output contains not the dates used to filter, but the actual min and max dates of the user attempts.
This code, of course, doesn't contain any validity checks on whether all the necessary xml tags present in the file, or whether values are valid dates and decimals...It's up to you to modify it under your certain needs.
You can use this Xml library that will enable to read the dates and sort by them.
XElement root = XElement.Load(file);
XElement david = root.XPathElement("//User[Name={0}]", "David");
XElement[] attempts = david
.XPath("Attempts[Date>={0} and Date<={1}]",
new DateTime(2012, 3, 29), new DateTime(2012, 8, 29))
.ToArray();

Categories