2013-03-07 40 views
0

我想將字符串轉換爲對象。 該字符串位於下面的語法中。對多個拆分的LINQ查詢的變化

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

並且說我要轉換的對象定義如下。

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

我cameup與下面的查詢

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

但是在這裏,我一次又一次地做在同一個字符串分割操作,我該如何避免這種情況, 沒有一個臨時變量。 此外,我忘記了這些風格的稱爲(名稱)像(from p in elements) LINQ查詢而不是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] }; 

謝謝:)

回答

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 benefit(s) of one over other?

0

這裏有一個解決方案,僅要求分割一次。你可以將它粘貼到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; 
    } 
}