[英]What's the most efficient way to change the last element in a '/' delimited string
[英]What's the most efficient way to parse a potentially bad delimited string into a class?
我正在构建一个自定义解析器,该解析器应读取定界数据列表,并将结果存储在类中。 我的问题是,生成数据的程序并不总是包含所有定界符。
例如,如果后3个属性没有值,它将跳过后3个定界符。
我一直在使用这样的东西,直到我注意到这个怪癖:
var data = message.Split(delimiter);
if (data.Length < 5)
throw new Exception("Invalid message");
Id = data[0];
Property1 = data[1];
Property2 = data[2];
Property3 = data[3];
Property4 = data[4];
当然,如果定界字符串包含的元素少于5个,则会产生问题。
将可能是错误的定界字符串解析为类的最佳方法是什么?
我不想为每个属性使用if
语句,因为某些定界字符串包含超过50个属性。
我曾想创建一个包含所有属性的数组,并在数据数组上运行一个for-each循环,但是我不确定这样做对性能有何影响,我想先看看是否有更好的方法。
假设属性为空
Property1 = data.Length > 1 ? data[1] : null;
Property2 = data.Length > 2 ? data[2] : null;
Property3 = data.Length > 3 ? data[3] : null;
Property4 = data.Length > 4 ? data[4] : null;
您可以使用对属性有意义的任何默认值来代替null
。
编辑:
var dataEx = new string[expectedLength];
data.CopyTo(dataEx, 0);
Property1 = dataEx[1];
Property2 = dataEx[2];
Property3 = dataEx[3];
Property4 = dataEx[4];
扩展方法怎么样?
public static T GetByIndexOrDefault<T>(this Array array, int index)
{
if (array == null)
{
return default(T);
}
if (index <= array.Length)
{
return (T)array.GetValue(index - 1);
}
return default(T);
}
然后:
string data = "foo1;foo2;foo3;foo4";
string[] splittedData = data.Split(';');
string e1 = splittedData.GetByIndexOrDefault<string>(1); // foo1
string e2 = splittedData.GetByIndexOrDefault<string>(2); // foo2
string e3 = splittedData.GetByIndexOrDefault<string>(3); // foo3
string e4 = splittedData.GetByIndexOrDefault<string>(4); // foo4
string e5 = splittedData.GetByIndexOrDefault<string>(5); // null
假设您的属性命名方案实际上类似于您的示例,则可以通过反射来实现:
var data = message.Split(delimiter);
if (data.Length < 1) throw new Exception("Invalid message");
Id = data[0];
for (var i = 1; i < data.Length; i++)
{
var property = GetType().GetProperty("Property" + i);
property.SetValue(this, data[i], null);
}
只要确保所有属性都具有可接受的默认状态,以防未通过message
设置它们。
创建属性数组将起作用,即。 Xander的答案,但是仍然不能解决不良数据的问题。 如果文件中间的字段分隔错误,则数组中间的属性也会出现问题。
但是,当您遇到问题时,我认为失败没有任何错。 如果消息格式错误,则该数据将是错误的。 如果您不需要创建缺少的字段,则总是可以手动解析消息并修复分隔错误的部分。
如果需要缺少字段,则某些应用程序会使用算法尝试修复错误的数据。 如果您认为数据可以固定(通过创建新数据或按摩旧数据),则可以创建一种“猜测”缺失字段的算法。
我会考虑对您的属性名称创建一个查找表,将属性的预期索引映射到其属性名称。 然后通过反射设置属性。
string[] propertyLookup = { "Property1", "Property2", "Property3", "Property4", "Property5" }; \\ etc etc
string[] parsedValues = message.Split(delimiter);
Foo newFoo = new Foo();
Type fooType = newFoo.GetType();
for (int i = 0; i < parsedValues.Count(); i++)
{
PropertyInfo prop = fooType.GetProperty(propertyLookup[i]);
prop.SetValue(newFoo, parsedValues[i], null);
}
using System;
using System.Windows.Forms;
using System.Reflection;
namespace DynamicProp
{
public partial class Form1 : Form
{
class Messagage
{
public string ID { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] data = { "hasan", "osman", "ali", "veli", "deli" };
Messagage message = new Messagage();
PropertyInfo[] ozellikler = message.GetType().GetProperties();
int I=0;
foreach (PropertyInfo ozellik in ozellikler)
{
ozellik.SetValue(message, data[I], null);
listBox1.Items.Add("özellik :" + ozellik.Name + " tipi :"+ozellik.GetValue(message,null).ToString());
I++;
}
}
}
}
提供另一种方式...
如果具有默认值(例如空字符串),则可以创建一个List并使用AddRange从数据字符串中添加值。 然后,如果尚未使用该特定数据的最大字段数,请使用AddRange和Enumerable.Repeat填写默认值。
List<string> Results = new List<string>();
int MaxFields = 5;
Results.AddRange(message.Split(delimiter));
if(Results.Count < MaxFields)
Results.AddRange(Enumerable.Repeat(String.Empty,MaxFields - Results.Count));
Id = Results[0];
Property1 = Results[1];
Property2 = Results[2];
Property3 = Results[3];
Property4 = Results[4];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.