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



我正在一个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;

提交表格时。int通过运行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逻辑。我可能在想某种查找表,但我不知道如何实现它,有什么可以查找的指针吗?

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

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

您可以使用反射和属性。

,中编写样本,并将其分隔为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;
}
}

如果有帮助,可以试试这个:

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

您可以使用ASCII代码,因此无需每次都添加if-else例如

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

最新更新