C#使用一个变量值从固定列表中设置第二个

时间:2018-12-13 05:46:23

标签: c# .net if-statement lookup-tables

我正在c#.net Windows窗体应用程序中解析CSV文件,将每一行带入我创建的类中,但是我只需要访问某些列,并且接收的文件没有标准化。也就是说,存在的字段数可以不同,并且列可以出现在任何列中。

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 :(得分:1)

您可以通过在标题中查找列的索引来使其自动,然后使用它们从其余各行的正确位置读取值:

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);
    }
}

答案 1 :(得分:1)

您可以使用反射和属性。

,中的示例写入DisplayName属性中。

首先使用csv标头字符串作为参数调用GetIndexes,以获取类属性和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;
    }
}

答案 2 :(得分:0)

如果有帮助,请尝试以下方法:

    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;
    }

答案 3 :(得分:-1)

您可以为此使用ASCII代码,因此无需每次添加 例如。

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