[英]String split to object with Linq?
鑒於:
class T
{
public string A { get; set; }
public string B { get; set; }
}
string s = "A|B";
有沒有辦法在|上拆分s? 並返回“內聯” T對象? 我知道我可以做類似的事情:
s.Select(x => { string[] arr = s.Split(); return new T() { A = arr[0], B = arr[1] };
但是我想知道是否有一些晦澀的linq事情可以“內聯”執行而不聲明數組並在select內部拆分。 以下方面的內容:
s.Split().Select(x => new T() { A = x[0], B = x[1] });
顯然,這會給您一個編譯器錯誤,但是您知道了...有沒有辦法做到這一點?
如果要一行完成,請確保:
var s = "A|B";
var t = new T{ A = s.Split('|')[0], B = s.Split('|')[1] };
但是很明顯,它兩次使用Split
,看起來很糟糕。
這可能表明您需要一種方法:
private static T ParseT(string s) {
// do the conversion *properly* here
}
然后,您可以調用它:
ParseT("A|B")
或者,添加顯式(推薦)或隱式轉換:
public static explicit operator T(string s) {
// do the conversion *properly* here
}
如果使用查詢語法,則可以執行以下操作:
var strings=new string[] { "A|B","C|D"};
var query= from s in strings
let x=s.Split('|')
select new T{ A = x[0], B = x[1] };
如果"A|B"
是數據源,我不建議為此使用Linq,則可以執行以下操作:
var arr= str.Split('|');
var instance=new T{A = arr[0],B=arr[1]};
或者在構造函數中執行與@James在其答案中建議的相同操作。
它實際上並沒有比您最初擁有的更好,但是這是一種方法(如果s是IEnumerable<string>
:
s.Select(x=>x.Split('|')).Select(x=>new T{A=x[0],B=x[1]});
如果s是單個字符串,則可以這樣做:
new List<string>{s} // Now List<string> with 1 string in the list
.Select(x=>x.Split('|')) // now IEnumerable<string[]> with 1 string array in it
.Select(x=>new T{A=x[0],B=x[1]}) // now IEnumerable<T> with 1 T in it
.First(); // Now just T
為什么要對抗實際的語言概念:
void Main()
{
var strs = new List<string> { "A|B", "CCC|DD", "E|FFF"};
var Ts = strs.Select(s =>s.ToT() );
Ts.Dump();
}
static class Ext
{
static public T ToT(this string str)
{
return new T(str);
}
}
public class T
{
public string A { get; set; }
public string B { get; set; }
public T(string str)
{
var arr= str.Split('|');
A = arr[0];
B = arr[1];
}
}
注意我不建議這樣做,這更有趣。
public static T CreateLinq(string s)
{
return s.Aggregate((a: new StringBuilder(), b: new StringBuilder(), c: false),
(acc, c) => (a: (!acc.c && c != '|' ? acc.a.Append(c) : acc.a),
b: (acc.c && c != '|' ? acc.b.Append(c) : acc.b),
c: acc.c || c == '|'),
acc => new T { A = acc.a.ToString(), B = acc.b.ToString() });
}
而且性能還不如乍看之下那么糟糕。
public class T
{
public string A { get; set; }
public string B { get; set; }
};
static void Main(string[] args)
{
var s1 = Enumerable.Range(0, 1000000).Aggregate(new StringBuilder(), (acc, i) => acc.Append("A")).ToString();
var s2 = Enumerable.Range(0, 1000000).Aggregate(new StringBuilder(), (acc, i) => acc.Append("B")).ToString();
var text =$"{s1}|{s2}";
for (int i = 0; i < 5; i++)
{
Stopwatch sw = new Stopwatch();
Console.WriteLine("Start");
sw.Start();
var t1 = CreateT(text);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var t2 = CreateLinq(text);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Reset();
}
Console.ReadLine();
}
public static T CreateLinq(string s)
{
return s.Aggregate((a: new StringBuilder(), b: new StringBuilder(), c: false),
(acc, c) => (a: (!acc.c && c != '|' ? acc.a.Append(c) : acc.a),
b: (acc.c && c != '|' ? acc.b.Append(c) : acc.b),
c: acc.c || c == '|'),
acc => new T { A = acc.a.ToString(), B = acc.b.ToString() });
}
public static T CreateT(string s)
{
var split = s.Split('|');
return new T { A = split[0], B = split[1] };
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.