c # использовать одно значение переменной, чтобы установить секунду из фиксированного списка - PullRequest
0 голосов
/ 13 декабря 2018

Я анализирую файл CSV в приложении ac # .net windows form, перенося каждую строку в созданный мною класс, однако мне нужен только доступ к некоторым столбцам И файлы, которые принимаются, не стандартизированы.То есть количество имеющихся полей может отличаться, и столбцы могут отображаться в любом столбце.

CSV Пример 1:

Position, LOCATION, TAG, NAME, STANDARD, EFFICIENCY, IN USE,,
1, AFT-D3, P-D3101A, EQUIPMENT 1, A, 3, TRUE
2, AFT-D3, P-D3103A, EQUIPMENT 2, B, 3, FALSE
3, AFT-D3, P-D2301A, EQUIPMENT 3, A, 3, TRUE
...

CSV Пример 2:

Position, TAG, STANDARD, NAME, EFFICIENCY, LOCATION, BACKUP, TESTED,,
1, P-D3101A, A, EQUIPMENT 1, 3, AFT-D3, FALSE, TRUE
2, P-D3103A, A, EQUIPMENT 2, 3, AFT-D3, TRUE, FALSE
3, P-D2301A, A, EQUIPMENT 3, 3, AFT-D3, FALSE, TRUE
...

Как видите, я никогда не узнаю формат файла, который мне нужно проанализировать, единственное, что я точно знаю, это то, что он всегда будет содержать несколько нужных мне столбцов.

Мое решениедля этого нужно было попросить пользователя ввести требуемые столбцы и установить их в виде строк, используя их запись, преобразовав это в соответствующее целое число, которое я мог бы затем использовать в качестве местоположения.

string standardInpt = "";
string nameInpt = "";
string efficiencyInpt = "";

пользователь затем введетзначение от A до ZZ.

int standardLocation = 0;
int nameLocation = 0;
int efficiencyLocation = 0;

при отправке формы.окончательные значения получают окончательные значения, выполняя оператор if else ...:

if(standard == "A")
{
  standardLocation = 0;
}
else if(standard == "B") 
{
  standardLocation = 1;
}
...

и т. д., выполняя весь путь, если VAR1 == ZZ, а затем код повторяется для VAR2, VAR3 и т. д..

Мой класс будет выглядеть примерно так:

class Equipment
{
  public string Standard { get; set;}
  public string Name { get; set; }
  public int Efficiency { get; set; }

  static Equipment FromLine(string line)
  {
     var data = line.split(',');

     return new Equipment()
     {
      Standard = data[standardLocation],
      Name = [nameLocation],
      Efficiency = int.Parse(data[efficiencyLocation]),
     };
   }
}

У меня там больше кода, но я думаю, что это подчеркивает, где я буду использовать переменные для установки индексов.

Я очень новичок в этом, и я надеюсь, что должен быть значительно лучший способ достичь этого без необходимости писать так много потенциально чрезмерной, повторяющейся логики If Else.Я думаю, что какая-то таблица поиска может быть, но я не могу понять, как реализовать это, какие-нибудь указатели на то, где я мог бы искать?

Ответы [ 4 ]

0 голосов
/ 13 декабря 2018

попробуйте это, если полезно:

    public int GetIndex(string input)
    {
        input = input.ToUpper();
        char low = input[input.Length - 1];
        char? high = input.Length == 2 ? input[0] : (char?)null;
        int indexLow = low - 'A';
        int? indexHigh = high.HasValue ? high.Value - 'A' : (int?)null;
        return (indexHigh.HasValue ? (indexHigh.Value + 1) * 26 : 0) + indexLow;
    }
0 голосов
/ 13 декабря 2018

Вы можете сделать это автоматически, найдя индексы столбцов в заголовке, а затем использовать их для считывания значений из правильного места из остальных строк:

class EquipmentParser {
    public IList<Equipment> Parse(string[] input) {
        var result = new List<Equipment>();

        var header = input[0].Split(',').Select(t => t.Trim().ToLower()).ToList();
        var standardPosition = GetIndexOf(header, "std", "standard", "st");
        var namePosition = GetIndexOf(header, "name", "nm");
        var efficiencyPosition = GetIndexOf(header, "efficiency", "eff");

        foreach (var s in input.Skip(1)) {
            var line = s.Split(',');
            result.Add(new Equipment {
                Standard = line[standardPosition].Trim(),
                Name = line[namePosition].Trim(),
                Efficiency = int.Parse(line[efficiencyPosition])
            });
        }

        return result;
    }

    private int GetIndexOf(IList<string> input, params string[] needles) {
        return Array.FindIndex(input.ToArray(), needles.Contains);
    }
}
0 голосов
/ 13 декабря 2018

Вы можете использовать отражение и атрибут.

Запишите свои образцы в ,, разделив их на DisplayName Атрибут.

Первый вызов GetIndexes со строкой заголовка csv в качестве параметра дляполучите словарь сопоставления свойств класса и полей csv.

Затем вызовите FromLine для каждой строки и словаря сопоставления, который вы только что получили.

class Equipment
{
    [DisplayName("STND, STANDARD, ST")]
    public string Standard { get; set; }
    [DisplayName("NAME")]
    public string Name { get; set; }
    [DisplayName("EFFICIENCY, EFFI")]
    public int Efficiency { get; set; }
    // You can add any other property

    public static Equipment FromLine(string line, Dictionary<PropertyInfo, int> map)
    {
        var data = line.Split(',').Select(t => t.Trim()).ToArray();
        var ret = new Equipment();
        Type type = typeof(Equipment);
        foreach (PropertyInfo property in type.GetProperties())
        {
            int index = map[property];
            property.SetValue(ret, Convert.ChangeType(data[index],
                property.PropertyType));
        }
        return ret;
    }

    public static Dictionary<PropertyInfo, int> GetIndexes(string headers)
    {
        var headerArray = headers.Split(',').Select(t => t.Trim()).ToArray();
        Type type = typeof(Equipment);
        var ret = new Dictionary<PropertyInfo, int>();
        foreach (PropertyInfo property in type.GetProperties())
        {
            var fieldNames = property.GetCustomAttribute<DisplayNameAttribute>()
                .DisplayName.Split(',').Select(t => t.Trim()).ToArray();
            for (int i = 0; i < headerArray.Length; ++i)
            {
                if (!fieldNames.Contains(headerArray[i])) continue;
                ret[property] = i;
                break;
            }
        }
        return ret;
    }
}
0 голосов
/ 13 декабря 2018

Вы можете использовать код ASCII для этого, поэтому нет необходимости добавлять, если еще каждый раз, например.

    byte[] ASCIIValues = Encoding.ASCII.GetBytes(standard);
    standardLocation  = ASCIIValues[0]-65;
...