2013-02-23 33 views
1

目標是對文本(即語音)進行排序,並將語音中不同單詞的列表輸出到文本框。我已經通讀了很多板子上的技巧,並且玩了很多,但是到了那個時候,我開始更加困惑。這裏是我的代碼如何在C#中使用LINQ返回不同的單詞列表?

private void GenerateList(string[] wordlist) 
    { 
     List<string> wordList = new List<string>(); 

     for (int i = 0; i < wordlist.Length; i++) 
     { 
      wordList.Add(wordlist[i]); 
     } 

     var uniqueStr = from item in wordList.Distinct().ToList() 
         orderby item 
         select item; 


     for (int i = 0; i < uniqueStr.Count(); i++) 
     { 
      txtOutput.Text = uniqueStr.ElementAt(i) + "\n"; 
     } 

    } 

在這一點上,我得到一個單詞的回報。對於我使用的文本(gettysburg地址),它是單詞「年」,它是文本中該單詞的唯一實例。

我傳遞函數加載到一個字符串數組,然後將其放入列表中的每個單詞(這可能是多餘的?)。

+3

請仔細觀看'txtOutput.Text = uniqueStr.ElementAt(i)+「\ n」' – 2013-02-23 02:40:35

回答

-1

下面是我如何簡化你的代碼,以及實現你想要達到的目標。

private void GenerateList(string[] wordlist) 
{ 
    List<string> wordList = wordlist.ToList(); // initialize the list passing in the array 


    var uniqueStr = from item in wordList.Distinct().ToList() 
        orderby item 
        select item; 


    txtOutput.Text = String.Join("\n", uniqueStr.ToArray()); 
} 
+0

這行不會被編譯,'wordList'是一個參數名稱,您不能將其重新定義爲變量。另外,實現'wordList'效率很低,因爲'wordList'是一個數組,它已經*成爲物化列表。在查詢中對ToList的調用也是不必要的,因爲沒有很好的理由實現列表(因爲它在那之後被排序並且該排序不在列表中完成)。 – casperOne 2013-02-23 17:11:54

+0

@casperOne再看一遍。變量是傳入的「wordlist」,而局部變量是大寫爲「L」的「wordList」。這是他的**原始**代碼,只是縮短了,並沒有證明-1票。 – 2013-02-24 01:59:12

+0

注意:投票不必是合理的,並且是匿名的。這表示它會編譯,但關於低效率的陳述仍然是正確的。 – casperOne 2013-02-24 02:42:31

-1

您可以使用該StringBuilder class與LINQ沿着流暢的界面,大大簡化了這一事實。

首先,你可以創建StringBuilder並連接所有的話到同一個實例,像這樣:

// The builder. 
var builder = new StringBuilder(); 

// A copy of the builder *reference*. 
var builderCopy = builder; 

// Get the distinct list, order by the string. 
builder = wordList 
    // Get the distinct elements. 
    .Distinct() 
    // Order the words. 
    .OrderBy(w => w). 
    // Append the builder. 
    Select(w => builderCopy.AppendLine(word)). 
    // Get the last or default element, this will 
    // cycle through all of the elements. 
    LastOrDefault(); 

// If the builder is not null, then assign to the output, otherwise, 
// assign null. 
txtOutput.Text = builder == null ? null : builder.ToString(); 

注意,你沒有真正兌現列表,如wordList已經一個物化列表,它是一個數組(在C#中鍵入的數組實現了IList<T> interface)。

AppendLine method(最上StringBuilder的方法)返回在其上執行的操作,這也就是爲什麼LastOrDefault method通話作品StringBuilder的實例;只需調用操作並返回結果(每個返回的項目將是相同的參考)。

builderCopy變量用於避免access to a modified closure(它從不傷害是安全的)。

在結束時的空校驗對於其中wordList不包含任何元素的情況。在這種情況下,對LastOrDefault的調用將返回null。

1

我希望這樣做,你在一個簡單而有效的方式需要(通過使用.dump()從LINQPad)

void Main() 
{ 
    // can be any IEnumerable<string> including string[] 
    var words = new List<string>{"one", "two", "four", "three", "four", "a", "z"}; 

    words.ToDistinctList().Dump(); 

    // you would use txtOutput.Text = words.ToDistinctList() 
} 

static class StringHelpers 
{ 
    public static string ToDistinctList(this IEnumerable<string> words) 
    { 
     return string.Join("\n", new SortedSet<string>(words)); 
    } 
} 
0

的一些技巧關於你的問題是什麼:

  • 沒有理由將數組轉換爲列表,因爲LINQ擴展方法定義在IEnumerable<T>上,這是由數組和列表實現的
  • 請確保所有字母都是相同的大小寫 - 使用ToLower,例如
  • 您在每次迭代中覆蓋txtOutput.Text。而不是設置新的價值,新的部分附加到現有的值

下面是一段簡單的代碼產生你想要的輸出:

IEnumerable<string> distinct = 
    wordList 
    .Select(word => word.ToLower()) 
    .Distinct() 
    .OrderBy(word => word); 

txtOutput.Text = string.Join("\n", distinct.ToArray()); 

在一個相關的說明,這裏是一個非常簡單的LINQ表達式,從文本,在整個文本中指定作爲一個字符串返回不同的話:

public static IEnumerable<string> SplitIntoWords(this string text) 
{ 

    string pattern = @"\b[\p{L}]+\b"; 

    return 
     Regex.Matches(text, pattern) 
      .Cast<Match>()       // Extract matches 
      .Select(match => match.Value.ToLower()) // Change to same case 
      .Distinct();       // Remove duplicates 

} 

你可以找到正則表達式的更多的變化在這裏同樣的問題:Regex and LINQ Query to Split Text into Distinct Words