我是一個初學者 c# 編碼員,我寫了一個小代碼,它計算字串中有多少不同的字符并回傳一個串列。我想讓這段代碼更有效率。
string s1 = "noob";
List<int> count = new();
foreach(var item in s1.Distinct()){
count.Add(s1.Count(x => x == item));
}
最終結果正是我想要的,一個值為 1,2,1 的 int 串列。
但是我完全意識到這確實效率低下(因為我必須遍歷每個字符的字串)。我試過使用 LINQ GroupBy 方法,但由于某種原因我無法將它分配給串列或 int[]。(我不知道如何從 IGrouping 轉換為陣列..)
我的邏輯在理論上很簡單。對所有字符進行分組,并為每個組回傳這些字符中有多少存在并將該值添加到陣列中。
我無法獨自解決這個問題,這讓我很生氣。我歡迎任何有關此事的提示或指導,并在此先感謝您。
uj5u.com熱心網友回復:
您可以使用GroupBy,而不是Distinct(我們組等于本地字符,選擇 Count各組,最后,兌現作為串列):
string s1 = "noob";
List<int> list = s1
.GroupBy(c => c)
.Select(group => group.Count())
.ToList(); // ToArray(); if you want an array
我們來看一下:
Console.Write(string.Join(", ", list));
結果:
1, 2, 1
uj5u.com熱心網友回復:
我的邏輯在理論上很簡單。對所有字符進行分組,并為每個組回傳這些字符中有多少存在并將該值添加到陣列中。
好邏輯
我無法獨自解決這個問題,這讓我很生氣。
Dmitry 給出了一個很好的答案,但讓我們談談 GroupBy,因為它令人困惑為 ****
如果你習慣了 SQL GROUP BY,這不是那么回事——它“中途停止”
在 SQL 中, GROUP BY 堅持你有一些你分組的東西,對于任何你沒有分組的東西,你必須提供一些聚合。以下是按部門統計的所有員工數,以及該部門的最高工資:
SELECT department, COUNT(*), MAX(salary) FROM emp GROUP BY department
dept, name, salary
tech, jon, 100000
tech, jane, 120000
sales, tim, 90000
--results
tech, 2, 12000
sales, 1, 90000
LINQ 在分組時不會這樣做;它運行分組,但它為您提供分成組的所有輸入資料,并且不堅持您進行任何聚合
在那里但由 LINQ 完成的相同的事情是:
employees.GroupBy(e => e.Department)
[
{ Key = "tech", self = [ { tech/jon/100000 }, { tech/jane/120000} ] },
{ Key = "tech", self = [ { sales/tim/90000 } ] }
]
這是一些偽 json 來描述您從 GroupBy 獲得的內容。你會得到一個分組串列。分組是“類似于串列”的東西,它有一個 Key 屬性,并且可以被列舉。如果您要求,Key您會得到分組的內容(部門名稱的字串)。如果您列舉分組,您將獲得擁有該密鑰的所有員工
var groups = employees.GroupBy(e => e.Department);
foreach(var group in groups){
Console.WriteLine("Now looking at the contents of the " g.Key " group");
foreach(var employee in group)
Console.WriteLine(" It's " employee.Name);
}
印刷:
現在查看 Tech 組的內容 這是 Jon 是 Jane 現在查看 Sales 組的內容 這是 Tim
因為這個串列是……嗯……一個可列舉的串列,你可以在上面呼叫其他 LINQ 方法
foreach(var group in groups){
Console.WriteLine("Now looking at the contents of the " g.Key " group");
Console.WriteLine(" The count is " group.Count());
Console.WriteLine(" The max salary is " group.Max(employee => employee .Salary));
}
現在查看Tech組的內容 計數為2 最高工資為120000 現在查看Sales組的內容 計數為1 最高工資為90000
通過中途停止而不是強迫您進行聚合,LINQ 為真正有用的東西敞開了大門
簡而言之,GroupBy 只是一個接受單個串列的設備:
Aaron
Albert
Bertie
Ben
Charlie
并將其轉換為串列串列:
GroupBy(name => name[0]) //first char
A: [Aaron, Albert]
B: [Bertie, Ben]
C: [Charlie]
請記住,為了避免混淆,請在 lambda 運算式中為變數命名
list_of_names
.GroupBy(name => name[0])
.Select(list_of_names_with_same_key => list_of_names_with_same_key.Count())
Remind yourself that what you're selecting is a list within a list, You might want to not use a name like list_of_names_with_same_key for that; I use g for "grouping" and I remember that a grouping is some enumerable list with a Key property that defines some value common to all
It's not so useful in this example, but also note that GroupBy has more overloads that the basic one but the docs are really tough to read. It's quite common to use the overload that lets you choose a different value..
//produces something like a List<string department, List<Employee>>
employees.GroupBy(emp => emp.Department)
//produces something like a List<string department, List<int>>
employees.GroupBy(emp => emp.Department, emp => emp.Salary)
The second one produces just salaries in the list of grouped items, which makes it easier to e.g.:
Console.WriteLine(" The max salary is " g.Max()); //g is a list of ints of salaies, not full employees
最后,它也可能有助于揭開 SelectMany 的神秘面紗——SelectMany 基本上與 GroupBy 相反。如果 GroupBy 將一個一維串列變成一個二維的東西,。SelectMany 將二維事物變成一維事物。你給 SelectMany 的東西應該是一個串列中的一個串列,你會得到一個串列(outerlist.SelectMany(someInnerList)導致所有內部串列連接在一起)。
你可以從字面上:
employees.GroupBy(emp => emp.Department).SelectMany(g => g)
然后回到你開始的地方
uj5u.com熱心網友回復:
var counts = "noob".GroupBy(c => c, (_, cs) => cs.Count());
Console.WriteLine("{0}", string.Join(",", counts)); // prints '1,2,1'
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/386041.html
