用Linq将字符串拆分为对象?

时间:2017-05-24 19:53:52

标签: c# linq

假设:

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

显然,这会给你一个编译器错误,但是你明白了......有没有办法像这样做?

5 个答案:

答案 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] };
        }