1

Presently my code is like this but I am wondering if there is a way that I could simplify it. What I am looking for is for one of the strings "JLPT N1","JLPT N2","JLPT N3","JLPT N4","JLPT N5" and then when I see one of these I will set the value of a phraseSources[seq].JishoJlpt.

Note that only one of the above can appear at once.

 if (nodes2[0].InnerText.Contains("JLPT N5")) { phraseSources[seq].JishoJlpt = "5"; } if (nodes2[0].InnerText.Contains("JLPT N4")) { phraseSources[seq].JishoJlpt = "4"; } if (nodes2[0].InnerText.Contains("JLPT N3")) { phraseSources[seq].JishoJlpt = "3"; } if (nodes2[0].InnerText.Contains("JLPT N2")) { phraseSources[seq].JishoJlpt = "2"; } if (nodes2[0].InnerText.Contains("JLPT N1")) { phraseSources[seq].JishoJlpt = "1"; } 

Would appreciate if anyone can suggest how I can simplify this.

2
  • 1
    is the N1,2,3.. going to be more than 9 ? Commented Oct 13, 2019 at 15:23
  • Do you control the format of the JSON data? Commented Oct 13, 2019 at 15:26

3 Answers 3

6

You should look into Regular Expressions.

This method would grab the int from your text, which you could then use.

 using System.Linq; using System.Text.RegularExpressions; public int ContainedNum(string s) { var match = Regex .Match(s, (@"JLPT N(\d{1})")) .Groups .Cast<Group>() .Skip(1) // the first match is the entire string not the group .Single() .Value; var num = int.Parse(match); return num; } 

This assumes that every argument always follows this pattern and doesn't go bigger than 9. If that isn't the case you would need to be more conservative using Single() and figure out what you want to return if that isn't case.

You could use it like this:

var text = nodes2[0].InnerText; var num = ContainedNum(text); phraseSources[seq].JishoJlpt = num.ToString(); 
Sign up to request clarification or add additional context in comments.

3 Comments

Wouldn't ^JLPT N(\d{1:3}) work for 1-3 digit numbers, for example, with no other changes?
Since the OP uses Contains I don't think you want to use the ^ anchor. Also there doesn't seem to be much point in parsing the number to an int to just turn around and format it back to a string.
@juharr Good call. I removed the ^. I realised the casting to an int is unnecessary, but when working with numbers I like to make that explicit in the signature.
1

I like the Try pattern for this kind of parsing:

private static bool TryParseJLPT(string text, out int value) { var match = Regex.Match(text, @"JLPT N(?<Number>\d+)", RegexOptions.None); if (!match.Success) { value = default; return false; } return Int32.TryParse(match.Groups["Number"].Value, out value); } 

Usage example:

if (TryParseJLPT(nodes2[0].InnerText, out int value)) { phraseSources[seq].JishoJlpt = value; } 

Depending on the case it may be more appropriate to throw instead of returning a boolean value. If a parsing failure is an expected case that can be handled, then the Try pattern is OK. If a parsing failure is exceptional and you don't know how to continue, then throwing is better.

Comments

-1

why not using an extension ?

I've been using This extension for a while :

internal static class Extensions { public static bool In(this string value, params string[] args) { return args.Contains(value); } } 

Applying the In extension on your code would be like this :

if (nodes2[0].InnerText.In("JLPT N1","JLPT N2","JLPT N3","JLPT N4","JLPT N5")) { phraseSources[seq].JishoJlpt = nodes2[0].InnerText.Last(); // get the last character } 

1 Comment

The OP's code is checking if any of those values are substrings of InnerText, so this will not work the same as their code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.