简体   繁体   中英

Extract index numbers from list of string

I have a list of strings where those strings have an index in each string and I need to extract the index from that string and put it in a List<int> .

Here's is a list example:

List<string> values = new List<string>();
values.Add("cohabitantGender");
values.Add("additionalDriver0LastName");
values.Add("additionalDriver0AgeWhenLicensed");
values.Add("vehicle0City");
values.Add("vehicle1City");
values.Add("vehicle2City");
values.Add("vehicle3City");

from this list I need to extract the indexes from the values vehicleXCity . I have this code right now:

public static List<int> FormObjectIndexExtractor(List<string> values, string prefix, string suffix)
{
    var selectedMatches = values.Where(v => v.StartsWith(prefix) && v.EndsWith(suffix)).Select(v=> v).ToList();
    var indexes = new List<int>();
    foreach (var v in selectedMatches) indexes.Add(int.Parse(Regex.Match(v, @"\d+").Value));
    return indexes;
}

And I'm using it like this:

List<int> indexes = FormObjectIndexExtractor(values, "vehicle", "City");

But if I have a value like vehicle4AnotherCity the code will work in the wrong way.

Does anyone have some alternative to this code that may help?

Below is an extension helper class incase you have a more robust list and you require multiple exclusion options

public class INumberList : List<string>
{ 
    public List<int> GetNumberList()
    {
        List<int> numberList = new List<int>();
        for (int i = 0; i < this.Count; i++)
        {
            numberList.Add(GetIntFromString(this[i]));
        }
        return numberList;
    } 
    public INumberList ExcludeIndex(string prefix, string suffix)
    {
        for (int i = 0; i < this.Count; i++)
        { 
            if (this[i].StartsWith(prefix) && this[i].EndsWith(suffix))
            {
                //remove non needed indexes
                this.RemoveAt(i);
            }
        }
        return this;
    }
    public static int GetIntFromString(String input)
    {
        // Replace everything that is no a digit.
        String inputCleaned = Regex.Replace(input, "[^0-9]", "");

        int value = 0;

        // Tries to parse the int, returns false on failure.
        if (int.TryParse(inputCleaned, out value))
        {
            // The result from parsing can be safely returned.
            return value;
        }

        return 0; // Or any other default value.
    }
}

Then use like this:

INumberList values = new INumberList();
        values.Add("cohabitantGender");
        values.Add("additionalDriver0LastName");
        values.Add("additionalDriver0AgeWhenLicensed");
        values.Add("vehicle0City");
        values.Add("vehicle1City");
        values.Add("vehicle2City");
        values.Add("vehicle3City");
//Get filtered index list with multiple exclusion option
List<int> indexList = values.ExcludeIndex("cohabitantGender","")
                        .ExcludeIndex("additionalDriver","AgeWhenLicensed")
                        .GetNumberList(); 
//will return [0,0,1,2,3]

Here is a solution (using modern C# features) that does not use Regex :

public static List<int> FormObjectIndexExtractor(IEnumerable<string> values, string prefix, string suffix)
{
  int? TryParseItem(string val)
  {
    if (val.Length <= prefix.Length + suffix.Length || !val.StartsWith(prefix) || !val.EndsWith(suffix))
      return null;

    var subStr = val.Substring(prefix.Length, val.Length - prefix.Length - suffix.Length);

    if (int.TryParse(subStr, out var number))
      return number;

    return null;
  }

  return values.Select(TryParseItem).Where(v => v.HasValue).Select(v => v.Value).ToList();
}

Try this:

public static List<int> FormObjectIndexExtractor(List<string> values, string prefix, string suffix)
{
    var s = "^" + prefix + @"(\d+)\.*?" + suffix + "$";
    return values
            .Where(v => Regex.Match(v, s).Success)
            .Select(v=> int.Parse(Regex.Match(v, s).Groups[1].Value))
            .ToList();
}

This version splits all the parts of string.

public static List<int> FormObjectIndexExtractor(List<string> values, string prefix, string suffix)
{
    List<int> ret = new List<int>();
    Regex r = new Regex("^([a-zA-Z]+)(\\d+)([a-zA-Z]+)$");
    foreach (var s in values)
    {
        var match = r.Match(s);
        if (match.Success)
        {
            if (match.Groups[1].ToString() == prefix && match.Groups[3].ToString() == suffix)
            {
                ret.Add(int.Parse(match.Groups[2].ToString()));
            }
        }
    }
    return ret;
}

or alternatively:

public static List<int> FormObjectIndexExtractor(List<string> values, string prefix, string suffix)
{
    List<int> ret = new List<int>();
    Regex r = new Regex($"^{prefix}(\d+){suffix}$");
    foreach (var s in values)
    {
        var match = r.Match(s);
        if (match.Success)
        {
            ret.Add(int.Parse(match.Groups[1].ToString()));
        }
    }
    return ret;
}

This is the more generic version.

  1. Regex match:

    • starts with 'vehicle'
    • matches a number
    • ends with 'city'.
  2. Parse and return as List<int>

      var indexes = values.Where(a => Regex.IsMatch(a, @"^vehicle\\d+City$")). Select(k => int.Parse(Regex.Match(k, @"\\d+").Value)).ToList(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM