Reputation: 2626
trying to select the max digit from a list of strings:
int maxDigit = this.myList.Where(x=> x.Name.Any(Char.IsDigit))
.Select(x => int.Parse(x.Name)).DefaultIfEmpty(0).Max();
It is int.Parse(x.Name)
which is causing an exception as this is returning the entire name string e.g. 'myValue99' which of course cannot be parsed to an int. I just want to return 99. I don't know where the digits will be in the string therefore cannot for example take the last two.
I need the DefaultIfEmpty for cases where the string does not contain a number.
Upvotes: 0
Views: 3965
Reputation: 151584
Assuming the input can contain the following categories:
null
sYou want to introduce a method that extracts the number, if any, or returns a meaningful value if not:
private static int? ParseStringContainingNumber(string input)
{
if (String.IsNullOrEmpty(input))
{
return null;
}
var numbersInInput = new String(input.Where(Char.IsDigit).ToArray());
if (String.IsNullOrEmpty(numbersInInput))
{
return null;
}
int output;
if (!Int32.TryParse(numbersInInput, out output))
{
return null;
}
return output;
}
Note that not all characters for which Char.IsDigit
returns true
can be parsed by Int32.Parse()
, hence the TryParse
.
Then you can feed your list to this method:
var parsedInts = testData.Select(ParseStringContainingNumber)
.Where(i => i != null)
.ToList();
And do whatever you want with the parsedInts
list, like calling IEnumerable<T>.Max()
on it.
With the following test data:
var testData = new List<string>
{
"۱", // Eastern Arabic one, of which Char.IsDigit returns true.
"123",
"abc456",
null,
"789xyz",
"foo",
"9bar9"
};
This returns:
123
456
789
99
Especially note the latest case.
Upvotes: 1
Reputation: 273219
Assuming you want the max number and not the max digit, all you need is a function to convert "stuff99"
to 99
. Then the Linq part becomes child's play:
int maxNumber = myList.Max(ExtractNumberFromText);
or, to be closer to your specs:
int maxNumber = myList
.Select(ExtractNumberFromText)
.DefaultIfEmpty(0)
.Max();
@Codecaster already pointed to a few applicable answers on this site for the second part. I adopted a simple one. No error checking.
// the specs: Only ever going to be my stuff1, stuff99
int ExtractNumberFromText(string text)
{
Match m = Regex.Match(text, @"\d*");
return int.Parse(m.Groups[0].Value); // exception for "abc"
// int.Parse("0" + m.Groups[0].Value); // use this for default to 0
}
Upvotes: 4
Reputation: 30022
It can be simple using Regex.
You stated 99, so you need to span more than one digit:
var maxNumber = myTestList.SelectMany(x => getAllNumnbersFromString(x.Name)).DefaultIfEmpty(0).Max();
static List<int> getAllNumnbersFromString(string str)
{
List<int> results = new List<int>();
var matchesCollection = Regex.Matches(str, "[0-9]+");
foreach (var numberMatch in matchesCollection)
{
results.Add(Convert.ToInt32(numberMatch.ToString()));
}
return results;
}
One digit only check:
int maxNumber = myTestList.SelectMany(x => x.Name.ToCharArray().ToList())
.Select(x => Char.IsDigit(x) ? (int)Char.GetNumericValue(x) : 0)
.DefaultIfEmpty(0).Max();
Upvotes: 0
Reputation: 1294
To find the max digit (not number) in each string:
static void Main(string[] args)
{
List<string> strList = new List<string>() { "Value99", "46Text" };
List<int> resultList = new List<int>();
foreach (var str in strList)
{
char[] resultString = Regex.Match(str, @"\d+").Value.ToCharArray();
int maxInt = resultString.Select(s => Int32.Parse(s.ToString())).Max();
resultList.Add(maxInt);
}
}
Upvotes: 0
Reputation: 347
Probably there's a slicker way to do this but I would just do:
int tmp = 0;
int maxDigit = this.myList.Where(x=> x.Name.Any(Char.IsDigit))
.Select(x =>
(int.TryParse(x.Name,out tmp ) ? int.Parse(x.Name) : 0 ) ).Max();
You have to remember that Parse will error out if it can't parse the value but TryParse will just give you false.
Upvotes: -1
Reputation: 45947
you should only select and parse the Digit characters out of your string
int maxDigit = this.myList.Where(x => x.Name.Any(Char.IsDigit))
.Select(x => int.Parse(new string(x.Name.Where(Char.IsDigit).ToArray())))
.DefaultIfEmpty(0).Max();
Upvotes: 3