简体   繁体   中英

Check if a particular string or string part exists in a List<string>

I have a function where I pass string value that should return me one string if that string or part of string (first 6 characters) exists in a list, if string or string part (first 6 characters) is not exists in list it should return null.

For example if search for:

EURUSD- it returns EURUSDf // good since EURUSD exists in list 
EURUSD  it returns EURUSDf // good since EURUSD exists in list
EURUSDf it returns EURUSDf // good since EURUSD exists in list
EURUSDu it returns EURUSDf // fail
EXCEUR is returns null     // good since EXCEUR is not exists in list

But what should it return for passed string is:

EURUSD- should return EURUSDf or EURUSDu // since EURUSD exists in list
EURUSD  should return EURUSDf or EURUSDu // since EURUSD exists in list
EURUSDf should return EURUSDf // since EURUSDf exists in list
EURUSDu should return EURUSDu // since EURUSDu exists in list
EXCEUR should return null     // since EXCEUR is not exists in list

Problem is probably because foreach loop goes through each line and it stops on first match it find. If you check in list it contains "EURUSDf", "EURUSDu" EURUSDf is always first so it will take him, it is ok on some cases but it is not if i search for EURUSDu strict and this returns me EURUSDf .

Since "EURUSDf", "EURUSDu" exists in list and i search for EURUSDu how to skip to it and return EURUSDu or if i search for EURUSDf to return EURUSDf ?

Here is code

string symbol = MapSymbol("EURUSDu"); // pass string and get output
Console.WriteLine($"Symbol is {symbol}"); // output

public static string MapSymbol(string symbol)
{
    try
    {
        symbol = symbol.Trim();
        string symbolReturn = "";

        List<string> symbolList = new List<string>() { "AUDCADu", "AUDJPYu", "AUDNZDu", "AUDUSDf", "AUDUSDu", "CADJPYu", "EURAUDu", "EURCADu", "EURCHFu", "EURGBPu", "EURJPYu", "EURNZDu", "EURUSDf", "EURUSDu", "GBPAUDu", "GBPCADu", "GBPCHFu", "GBPJPYu", "GBPNZDu", "GBPUSDf", "GBPUSDu", "GER30u", "HK50u", "JPN225u", "NAS100u", "NZDCADu", "NZDUSDf", "NZDUSDu", "SPX500u", "UK100u", "UKOILu", "US30u", "USDCADf", "USDCADu", "USDCHFf", "USDCHFu", "USDJPYf", "USDJPYu", "USDXu", "USOILu", "XAGUSDf", "XAGUSDfv", "XAGUSDu", "XAUUSDf", "XAUUSDfv", "XAUUSDu", "XINA50u" };

        foreach (var item in symbolList)
        {
            if (item == symbol)
            {
                symbolReturn = item; break;
            }
            else if (item == symbol.Substring(0, Math.Min(symbol.Length, 6)))
            {
                symbolReturn = item; break;
            }
            else if (item.Substring(0, Math.Min(item.Length, 6)) == symbol)
            {
                symbolReturn = item; break;
            }
            else if (item.Substring(0, Math.Min(item.Length, 6)) == symbol.Substring(0, Math.Min(symbol.Length, 6)))
            {
                symbolReturn = item; break;
            }
            else
            {
                symbolReturn = null;
            }
        }
        return symbolReturn;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception in maping symbol, {ex.Message}");
        return null;
    }
}

You could try such method:

static List<string> symbolList = new List<string>() { ... };

public static string MapSymbol(string symbol)
{
  // we have exact match
  if (symbolList.Contains(symbol)) return symbol;
  // look for first 6 character match
  var sixCharPrefix = symbol.Substring(0, 6);
  // returns first matched string, if not found return default for string, which is null
  return symbolList.FirstOrDefault(s => s.StartsWith(sixCharPrefix));
}

If you don't want to traverse the list multiple times or use linq, then you could introduce the concept of priority:

public static string MapSymbol(string symbol)
{
    try
    {
        symbol = symbol.Trim();
        string symbolReturn = null;
        int priority = 5;

        List<string> symbolList = new List<string>() { "AUDCADu", "AUDJPYu", "AUDNZDu", "AUDUSDf", "AUDUSDu", "CADJPYu", "EURAUDu", "EURCADu", "EURCHFu", "EURGBPu", "EURJPYu", "EURNZDu", "EURUSDf", "EURUSDu", "GBPAUDu", "GBPCADu", "GBPCHFu", "GBPJPYu", "GBPNZDu", "GBPUSDf", "GBPUSDu", "GER30u", "HK50u", "JPN225u", "NAS100u", "NZDCADu", "NZDUSDf", "NZDUSDu", "SPX500u", "UK100u", "UKOILu", "US30u", "USDCADf", "USDCADu", "USDCHFf", "USDCHFu", "USDJPYf", "USDJPYu", "USDXu", "USOILu", "XAGUSDf", "XAGUSDfv", "XAGUSDu", "XAUUSDf", "XAUUSDfv", "XAUUSDu", "XINA50u" };

        foreach (var item in symbolList)
        {
            if (item == symbol)
            {
                symbolReturn = item; 
                break; // best priority so no need to look at the rest of the list
            }
            else if (priority > 2 && item == symbol.Substring(0, Math.Min(symbol.Length, 6)))
            {
                priority = 2;
                symbolReturn = item;
            }
            else if (priority > 3 && item.Substring(0, Math.Min(item.Length, 6)) == symbol)
            {
                priority = 3;
                symbolReturn = item;
            }
            else if (priority > 4 && item.Substring(0, Math.Min(item.Length, 6)) == symbol.Substring(0, Math.Min(symbol.Length, 6)))
            {
                priority = 4;
                symbolReturn = item;
            }
        }

        return symbolReturn;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception in maping symbol, {ex.Message}");
        return null;
    }
}

One solution I can offer is that you extract your tests in a separate collection using the Func data type, the position will be the priority here. Then you go test rule by test rule and iterate through your collection. If the first rule gives you a positive result, then you stop looking. If not, then you iterate again using the next rule and so on. I hope you get the drift.

public static string MapSymbol(string symbol)
{
    try
    {
        symbol = symbol.Trim();
        string symbolReturn = "";

        List<string> symbolList = new List<string>() { "AUDCADu", "AUDJPYu", "AUDNZDu", "AUDUSDf", "AUDUSDu", "CADJPYu", "EURAUDu", "EURCADu", "EURCHFu", "EURGBPu", "EURJPYu", "EURNZDu", "EURUSDf", "EURUSDu", "GBPAUDu", "GBPCADu", "GBPCHFu", "GBPJPYu", "GBPNZDu", "GBPUSDf", "GBPUSDu", "GER30u", "HK50u", "JPN225u", "NAS100u", "NZDCADu", "NZDUSDf", "NZDUSDu", "SPX500u", "UK100u", "UKOILu", "US30u", "USDCADf", "USDCADu", "USDCHFf", "USDCHFu", "USDJPYf", "USDJPYu", "USDXu", "USOILu", "XAGUSDf", "XAGUSDfv", "XAGUSDu", "XAUUSDf", "XAUUSDfv", "XAUUSDu", "XINA50u" };

        // functions can be saved as Func<string, string, bool>
        // that means it takes 2 strings as input parameters and returns a bool
        List<Func<string, string, bool>> TestCases = new List<System.Func<string, string, bool>>()
        {
            (item, sym) => item == sym,
            (item, sym) => item == sym.Substring(0, Math.Min(sym.Length, 6)),
            (item, sym) => item.Substring(0, Math.Min(item.Length, 6)) == sym.Substring(0, Math.Min(sym.Length, 6))
        };

        bool matchFound = false;
        // iteration over each test rules
        foreach (var test in TestCases)
        {
            // iteration ver your collection
            foreach (var item in symbolList)
            {
                // test for a match
                if(test(item, symbol))
                {
                    matchFound = true;
                    symbolReturn = item;
                }
            }

            if (matchFound)
            {
                break;
            }
        }

        return matchFound ? symbolReturn : null;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception in maping symbol, {ex.Message}");
        return null;
    }   
}

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