0

I want to transform a string to a object. The string is in the below syntax.

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

and say the object to which I want to transform this is defined as below.

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

I cameup with the below query

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

Also I prefer writing sql type linq queries so I thought I will split down the above query and came up with the below solutions

    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[]

and I didn't want to call a helper function :-

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

Notice in the last query I have used a dummyContainer and invoking the Where() only to load the dummyContainer. I wanted to rewrite the last query without using a dummy variable or a external function call, however I was not able to comeup with a viable solution.

I can write something like below

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

But here I am doing the split operation on the same string again and again, how do I avoid this, without a temporary variable. Also I forgot what are these style of LINQ queries called(name) like (from p in elements) instead of elements.Select() are called.

Also I would like to know how I can rewrite the very first query in this post, without call to the ReturnObject function

I researched further and found 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] };

Thanks :)

Vignesh.N
  • 2,618
  • 2
  • 25
  • 33

2 Answers2

2

You can use let, something like this :

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

And if you want it to return MyStruct instead of an anonymous class object, try this :

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

As for the LINQ syntax, I believe what you mean is fluent vs query expression.

You can read more about it here : LINQ - Fluent and Query Expression - Is there any benefit(s) of one over other?

Community
  • 1
  • 1
andri
  • 1,021
  • 1
  • 9
  • 16
0

Here's a solution that only calls Split once. You can paste this into LINQPad to try it. I don't think there's an equivalent Unzip method in LINQ but I'm happy to learn otherwise.

This solution depends on there being no empty name or id entries.

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;
    }
}
Phil
  • 42,255
  • 9
  • 100
  • 100