Reputation: 642
I am completely stumped on how to achieve this. Basically, I want to find the ceiling in a METAR report. The ceiling is the smallest broken or overcast layer.
I currently have this (which is not much by any means):
MatchCollection matches = Regex.Matches(modify, @"(BKN|OVC)([0-9]{3})");
foreach (Match match in matches)
{
foreach (Capture capture in match.Captures)
{
// compare broken and overcast layers to find smallest value and set as the ceiling
Console.WriteLine(capture.Value);
}
}
Basically this searches the METAR string for BKN or OVC layers and spits them out. Take this METAR reading for example:
PANC 040553Z 17013G24KT 280V360 2SM FEW050 BKN019 BKN008 OVC005 14/M07 A2999 RMK AO2 SLP156 SH DSNT W-N T01390067 10167 20139 53002
The code I currently have will spit out BKN019, BKN008 and OVC005. What I need to do, is pick the smallest of these values (which, in this case, would be OVC005).
If someone can help me, I would greatly appreciate it.
Upvotes: 0
Views: 592
Reputation: 21764
Try using capturing groups:
// (?<number> names the group that captures the number value
var matches = Regex.Matches(modify, @"(BKN|OVC)(?<number>[0-9]{3})");
// cast to IEnumerable<Match>()
var smallest = matches.Cast<Match>()
// order by the parsed number group
// Added `.Value` to make this work
.OrderBy(m => int.Parse(m.Groups["number"].Value))
// Select the string value
.Select(m => m.Value)
// take the first (the smallest)
.FirstOrDefault();
if smallest is null
then no matches found
Upvotes: 3
Reputation: 18474
Linq
is your friend
remember using System.Linq
MatchCollection matches = Regex.Matches(modify, @"(BKN|OVC)([0-9]{3})");
var first = (
from x in matches.OfType<Match>()
orderby int.Parse(x.Groups[2].Value)
select x.Value
).FirstOrDefault();
Upvotes: 0
Reputation: 14880
If I understand correctly, you want to take the whole capture for the smallest 2nd group.
matches.OfType<Match>()
.Select(m => new { Capture = m.Groups[0], Number = Int32.Parse(m.Groups[2]) })
.OrderBy(m => m.Number)
.Select(m => m.Capture)
.FirstOrDefault();
Upvotes: 1
Reputation: 9270
Basically what you want to do is keep track of the lowest layer found so far and then check for each regex match whether it's lower than before:
int lowestLayer = int.MaxValue;
MatchCollection matches = Regex.Matches(modify, @"(BKN|OVC)([0-9]{3})");
foreach (Match match in matches)
{
foreach (Capture capture in match.Captures)
{
int layer = int.Parse(capture.Value.Substring(3));
if (layer < lowestLayer)
lowestLayer = layer;
Console.WriteLine(capture.Value);
}
}
Upvotes: 1