Próbuję znaleźć najbardziej wydajny sposób klasyfikacji wydatków na oprogramowaniu do rachunkowości. Wartości są w ten sposób:

"EFTPOS Kathmandu 2342342"

Stworzyłem metodę w następujący sposób:

  private static string Classifier(string inputDescription)
        {
            Dictionary<string, string> classified = new Dictionary<string, string>();
            classified.Add("D/C FROM", "INCOME" );
            classified.Add("CREDIT ATM", "INCOME");
            classified.Add("INTEREST", "INCOME");

        classified.Add("EFTPOS", "EXPENSE" );
        classified.Add("DEBIT DEBIT", "EXPENSE");
        classified.Add("CC DEBIT", "EXPENSE");

        classified.Add("PAYMENT RECEIVED", "TRANSFER");
        classified.Add("PAYMENT - THANK YOU", "TRANSFER");

        classified.Add("IRD", "TAX" );
        classified.Add("I.R.D", "TAX");

        try
        {
           // What do I do here to get the value?
            return value;

        }
        catch(Exception)
        {
            return "OTHER";
        }

    }

Zasadniczo chcę przejść przez wartości mojej wprowadzania do kluczy w słowniku, aby uzyskać jego wartość (klasyfikacja elementu linii).

Tak więc dla przykładu pokazanego powyżej, wynik byłby "wydatek".

Zakładałem, że słownik byłby najszybszym sposobem podejścia do tego, ale otwarty na sugestie dotyczące lepszych metod.

Z góry dziękuję!

0
Jay J 4 czerwiec 2018, 08:11

4 odpowiedzi

Najlepsza odpowiedź

A co z użyciem REGEX?

const string EXPENSE_PATTERN = "^(EFTPOS|DEBIT DEBIT|CC DEBIT)"
const string ..._PATTERN

if (Regex.IsMatch(input, EXPENSE_PATTERN)){
    return "EXPENSE";
} else if (Regex.IsMatch(input, INCOME_PATTERN)){
    return "INCOME";
} else if (Regex.IsMatch(input, ..._PATTERN)){
    return "...";
} else {
    return "OTHER"
}
1
Tobias 4 czerwiec 2018, 05:56

Jednym ze sposobów, aby to osiągnąć

string input = "EFTPOS Kathmandu 2342342";
string value = string.Empty;

foreach (var key in input.Split(' '))
{
   value = classified.Where(k => classified.ContainsKey(k.Key)).Select(k => classified[k.Key]).FirstOrDefault();

   if(value != null & value.trim()!= string.empty)
        break;
}

Sprawdź value jest null lub nie do dalszego użycia. Pętla Foreach pęknie raz znajdzie wartość.

0
Gaurang Dave 4 czerwiec 2018, 05:38

Metoda dzwonka:

    static void Main(string[] args)
    {
        Console.WriteLine(Classifier("EFTPOS Kathmandu 2342342"));
        Console.WriteLine(Classifier("D/C FROM Kathmandu 2342342"));
        Console.ReadKey();
    }

Metoda klasyfikatora:

    private static string Classifier(string inputDescription)
    {
        var classified = new Dictionary<string, string>
        {
            { "D/C FROM", "INCOME" },
            { "CREDIT ATM", "INCOME" },
            { "INTEREST", "INCOME" },
            { "EFTPOS", "EXPENSE" },
            { "DEBIT DEBIT", "EXPENSE" },
            { "CC DEBIT", "EXPENSE" },
            { "PAYMENT RECEIVED", "TRANSFER" },
            { "PAYMENT - THANK YOU", "TRANSFER" },
            { "IRD", "TAX" },
            { "I.R.D", "TAX" }
        };

        try
        {
            foreach (var kvp in classified)
                if (inputDescription.StartsWith(kvp.Key))
                    return kvp.Value;

            return "OTHER";
        }
        catch
        {
            return "OTHER";
        }
    }

Zwroty:

EXPENSE
INCOME

Oczywiście można przenieść definicję słownika poza metodą i uczynić go członkiem klasy. To byłoby szczególnie sens, jeśli masz wiele częstych połączeń do Classifier. Możesz także zdefiniować go jako IReadOnlyDictionary, aby zapobiec zmianom jego zawartości.

0
Mike Lowery 4 czerwiec 2018, 06:18

Najprostszym sposobem na uzyskanie czegoś z słownika jest używając klucza takiego jak:

Dictionary<string, string> classified = new Dictionary<string, string>();

var value = classified[key];

Ale oczywiście chciałbyś sprawdzić kluczowego wystąpienia w słowniku takiej jak:

if(classified.ContainsKey(key))
     return classified[key];
else
         throw new InvalidTypeException();//this is because you should have all the key's mapped i.e you are only expecting known key types.People prefer other types like they would return null but i throw coz my dictionary is not having this key

Teraz zbliża się do wartości:

Wszystkie wartości wydają się być znane i powtarzane typy. Więc zbudowałem enum:

enum TransactionType
{
Expense,
Income,
Transfer
}

enum Source
{
EFTPOS,
DEBIT DEBIT,
...so on...
}
   i prefer enums to avoid magic strings and people do make mistakes while typing strings.

Tak więc z kombinacją słownika i enum teraz zbudowałem jako:

private Dictionary<Source,TransactionType> PopulateSource()
{
Dictionary<Source,TransactionType> classified = new Dictionary<Source,TransactionType>();
//populate dictionary by iterating using
 var keys = Enum.GetValues(typeof(Source)); 
 var values = Enum.GetValues(typeof(TransactionType));
you can just iterate through keys if your keys and values in enum are in order .

return classified ;
}

public void TestSourceTransaction()
{
TransactionType transType;
var classifieds = PopulateSource();
var key  = GetSourceType(inputDescription);//you need to write a method to get key from desc based on regex or string split options.
if(classifieds.ContainsKey(key))
          classifieds[key].Value;
else
         throw new InvalidTypeException("Source type undefined");
}

Wolę czysty i rozszerzalny kod i bezwzględny ciąg magiczny.

0
Dharani Kumar 4 czerwiec 2018, 06:45