假设:
class T
{
public string A { get; set; }
public string B { get; set; }
}
string s = "A|B";
有没有办法在|上拆分并返回一个T对象"内联"?我知道我可以这样做:
s.Select(x => { string[] arr = s.Split(); return new T() { A = arr[0], B = arr[1] };
但是我想知道是否有一些模糊不清的linq要做的事情" inline"没有声明数组并在select内部分裂。更多的东西:
s.Split().Select(x => new T() { A = x[0], B = x[1] });
显然,这会给你一个编译器错误,但是你明白了......有没有办法像这样做?
答案 0 :(得分:3)
如果您想在一行中执行此操作,请确保:
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
}
答案 1 :(得分:2)
如果您使用查询语法,那么您可以执行以下操作:
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在答案中推荐的那样。
答案 2 :(得分:1)
这并不比你原来的好,但这是一种方式(如果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
答案 3 :(得分:0)
为什么要打击实际的语言概念:
applicationVariants.all{}
答案 4 :(得分:0)
注意我不建议这样做,这是一种更有趣的方式。
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] };
}