0

我想将字符串转换为对象。该字符串采用以下语法。

string nameIdPair = "name1:123\r\nname2:456\r\n";

并说我想要将其转换为的对象定义如下。

    public struct MyStruct
    {
        public string Name;
        public int Id;
    }

我想出了以下查询

    var elements = nameIdPair.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
        .Where(p => !string.IsNullOrWhiteSpace(p))
        .Select(r => r.Split(':'))
        .Select(s => ReturnObject(s));

另外我更喜欢编写 sql 类型的 linq 查询,所以我想我会拆分上面的查询并提出以下解决方案

    var elements = from p in nameIdPair.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
                   where !string.IsNullOrWhiteSpace(p)
                   select ReturnObject(p); // Here p is string not string[]

而且我不想调用辅助函数:-

    string[] tempContainer = new string[] { };
    var elements = from p in nameIdPair.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
                   where (tempContainer = p.Split(':')) != null
                   select new { name = tempContainer[0], id = tempContainer[1] };

    private static object ReturnObject(string inputString)
    {
        string[] value = inputString.Split(':');
        myObject.Name = value[0];
        myObject.Id = int.Parse(value[1]);
        return myObject;
    }

请注意,在最后一个查询中,我使用了一个 dummyContainer 并调用 Where() 只是为了加载 dummyContainer。我想在不使用虚拟变量或外部函数调用的情况下重写最后一个查询,但是我无法提出可行的解决方案。

我可以写如下

var elements = from p in nameIdPair.Split(new string[] { "\r\n", "\n" },StringSplitOptions.RemoveEmptyEntries)
               select new { name = p.Split(':')[0], id = p.Split(':')[1] };

但是在这里我一次又一次地对同一个字符串进行拆分操作,我该如何避免这种情况,没有临时变量。我也忘记了这些风格的 LINQ 查询称为(名称),(from p in elements)而不是elements.Select()被调用。

另外我想知道如何在不调用 ReturnObject函数的情况下重写这篇文章中的第一个查询

我进一步研究发现let

var items = from p in nameIdPair.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
            let r = p.Split(':')
            select new { name = r[0], id = r[1] };

谢谢 :)

4

2 回答 2

2

你可以使用let,像这样:

var elements = from p in nameIdPair.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
               let arr = p.Split(':')
               select new { name = arr[0], id = arr[1] };

如果您希望它返回MyStruct而不是匿名类对象,请尝试以下操作:

var elements = from p in nameIdPair.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
               let arr = p.Split(':')
               select new MyStruct { Name = arr[0], Id = int.Parse(arr[1]) };

至于 LINQ 语法,我相信你的意思是流利的 vs 查询表达式。

您可以在此处阅读更多相关信息:LINQ - Fluent and Query Expression - Is there any benefits(s) of one over other?

于 2013-03-07T05:50:51.480 回答
0

这是一个只调用 Split 一次的解决方案。您可以将其粘贴到 LINQPad 中进行尝试。我认为 LINQ 中没有等效的 Unzip 方法,但我很乐意学习其他方法。

此解决方案取决于没有空名称或 id 条目。

void Main()
{
    string nameIdPair = "name1:123\r\nname2:456\r\n";

    var strings = nameIdPair.Split(new string[]{ "\r\n", "\r", ":" }, 
                                   StringSplitOptions.RemoveEmptyEntries);
    var structs = strings.Unzip();

    structs.Dump();
}

public struct MyStruct
{
    public string Name;
    public int Id;
}

static class Helpers
{
    public static IEnumerable<MyStruct> Unzip(this IEnumerable<string> items)
    {
        using(var en = items.GetEnumerator())
        {
            string name = null;

            while(en.MoveNext())
            {
                if(name == null){
                    name = en.Current;
                }
                else{
                    int id = int.Parse(en.Current);
                    yield return new MyStruct{Name = name, Id = id};
                    name = null;
                }
            }
        }

        yield break;
    }
}
于 2013-03-07T09:05:09.343 回答