Powered By Blogger

關於我自己

我的相片
網站經營斷斷續續,現在以分享程式練習為主。 因為工作需要,不時會有練習程式的需要。 所以將自己練習的過程分享給大家。 如果有幫助到各位,那就太好了! 如果針對本人或網站內容有任何問題, 歡迎與我聯絡。

2021年1月31日 星期日

【C# 語言】三種尋找 List 中資料的方法 ForEach、FindAll、Linq Where Select

居裡貓最近跟人討論到幾個尋找List中尋找特定資料的方法,所以順便做了這個練習。
接下來就讓我們看看到底這幾種方法怎麼使用囉!
在很多時候我們會有一些資料,它會有自己特有的內容以及規則,
有一些時候需要去尋找資料集中特定的資料內容,
但是資料一旦很多的時候,通常都是使用迴圈來一筆一筆確認,
在某些時候迴圈是很好用的東西,但寫作上不那麼便利跟迅速,
剛好這些條件的設計下,有除了迴圈以外的方法。

今天要介紹練習的就是這三種方法:

For Each

List.FindAll

Linq - Where Select

這三種方法的後面兩種,就是一種寫作方式便利快速的作法,
但是處理的結果也跟常用的迴圈相同。

今天居裡貓設計了一個資料格式類別,包含 No, Name, Score 的資料格式。

  1. public class DataClass  
  2. {  
  3.     public int No { getset; }  
  4.     public string Name { getset; }  
  5.     public int Score { getset; }  
  6.   
  7.     public DataClass(int _no, string _name, int _score)  
  8.     {  
  9.         No = _no;  
  10.         Name = _name;  
  11.         Score = _score;  
  12.     }  
  13. }  

根據這樣的資料格式,來尋找特定的成績大於某數的結果,
利用上面提到的三個方法來尋找這樣的結果。

接著就來說明一下這個練習的程式設計樣式:




介面中包含幾個元件,說明如下:
Reset Data : 根據後方 NumericUpDown 裡面的數值初始化上述說明的資料格式。
For Each : 利用 For Each 的方法,尋找成績大於 Find Score 後方 NumericUpDown 數值的數。
Find All : 利用 List.FindAll 的方法,尋找成績大於 Find Score 後面 NumericUpDown 數值的數。
Linq Select : 利用 Linq 中 Where 和 Select 的方法,尋找成績大於 Find Score 後面 NumericUpDown 數值的數。
Original Data : 是這次資料的總資料內容。
Find Data : 是尋找成功的資料內容。

介紹完介面之後,讓我們來看一下尋找的結果吧!



橘色框線內為 For Each 的搜尋結果,花費時間跟尋找的筆數。
綠色框線內為 Find All 的搜尋結果,花費時間跟尋找的筆數。
紫色框線內為 Linq Select 的搜尋結果,花費時間跟尋找的筆數。

針對花費的時間來看,便利的寫法並不一定會得到更好的時間花費,
在相同搜尋結果下,如果在需要更快速的處理速度,更少的花費時間,
For Each 的作法不見得不好,
但不要求快速的處理始間下,另外兩種方法的便利寫法、較簡單的程式碼,
或許會讓閱讀的狀態更為良好。

接下來就來看看程式碼吧!
本次範例的介面設計皆由程式碼產生,
所以以下程式碼中會看到介面設計的方法內容,請見諒。



-------------------------------程式碼分割線------------------------------------------------------------

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Threading.Tasks;  
  9. using System.Windows.Forms;  
  10.   
  11. using System.Diagnostics;  
  12.   
  13. namespace TestFindListData  
  14. {  
  15.     public partial class MainForm : Form  
  16.     {  
  17.         #region Fields  
  18.         private Button _btnUITest;  
  19.         private Button[] _btnFunction;  
  20.         private Label[] _lblFunctionCost;  
  21.         private NumericUpDown[] _nudDataNumber;  
  22.         private ListBox[] _lsbDataInfo;  
  23.         private List<DataClass> _lsData;         
  24.         private List<DataClass> _lsFindScore;  
  25.         private Random _rndScore;  
  26.         private Stopwatch _sw;  
  27.         #endregion // Fields  
  28.  
  29.         #region Construct  
  30.         public MainForm()  
  31.         {  
  32.             InitializeComponent();  
  33.   
  34.             Initial();  
  35.         }  
  36.         #endregion // Construct  
  37.  
  38.         #region Event  
  39.         private void btnUITest_Click(object sender, EventArgs e)  
  40.         {  
  41.             this.Controls.Clear();  
  42.   
  43.             Initial();  
  44.         }  
  45.   
  46.         private void btnFunction_Click(object sender, EventArgs e)  
  47.         {  
  48.             Button _tmpBtn = (Button)sender;  
  49.             switch (_tmpBtn.Name)  
  50.             {  
  51.                 case "btnFunctionData":  
  52.                     InitialTestData(Convert.ToInt32(_nudDataNumber.First(x=>x.Name == "nudDataCount").Value));  
  53.                     break;  
  54.                 case "btnFunctionFor":  
  55.                     FunctionForEach(_lsData, Convert.ToInt32(_nudDataNumber.First(x => x.Name == "nudScore").Value));  
  56.                     break;  
  57.                 case "btnFunctionFind":  
  58.                     FunctionFindAll(_lsData, Convert.ToInt32(_nudDataNumber.First(x => x.Name == "nudScore").Value));  
  59.                     break;  
  60.                 case "btnFunctionLinq":  
  61.                     FunctionLinq(_lsData, Convert.ToInt32(_nudDataNumber.First(x => x.Name == "nudScore").Value));  
  62.                     break;  
  63.             }  
  64.         }  
  65.         #endregion // Event  
  66.  
  67.         #region Function  
  68.  
  69.         #region Private Function  
  70.         private void Initial()  
  71.         {  
  72.             this.Width = 640;  
  73.             this.Height = 640;  
  74.   
  75.             // CreateButtonWithUI();    // This function will create UI reset function  
  76.   
  77.             CreateButtonWithFunction(4);  
  78.             CreateLabelWithFunctionCost(6);  
  79.             CreateNumbericUpDown(2);  
  80.             CreateListbox(2);  
  81.   
  82.             InitialTestData(10);  
  83.         }  
  84.   
  85.         private void InitialTestData(int _total)  
  86.         {  
  87.             if (_lsData == null)  
  88.             {  
  89.                 _lsData = new List<DataClass>();  
  90.             }  
  91.   
  92.             if (_lsData.Count > 0)  
  93.             {  
  94.                 _lsData.Clear();  
  95.                 _lsData = new List<DataClass>();  
  96.             }  
  97.   
  98.             _rndScore = new Random();  
  99.   
  100.             for (int i = 0; i<_total;i++)  
  101.             {  
  102.                 _lsData.Add(new DataClass(i, Convert.ToString((char)(i+65)), _rndScore.Next(0, 100)));  
  103.             }  
  104.               
  105.             if (_lsbDataInfo.First(x => x.Name == "lsbOriginalData").Items.Count > 0) { _lsbDataInfo.First(x => x.Name == "lsbOriginalData").Items.Clear(); }  
  106.             foreach (var tmp in _lsData)  
  107.             {  
  108.                 _lsbDataInfo.First(x => x.Name == "lsbOriginalData").Items.Add("No: " + tmp.No.ToString() + " Name: " + tmp.Name + " Score: " + tmp.Score);  
  109.             }  
  110.         }  
  111.   
  112.         private void FunctionForEach(List<DataClass> _ls, int _findScore)  
  113.         {  
  114.             if (_ls == null) { MessageBox.Show("The data list is null so will return FunctionForEach"); return; }  
  115.   
  116.             _lsFindScore = new List<DataClass>();  
  117.             _sw = new Stopwatch();  
  118.             _sw.Reset();  
  119.             _sw.Start();  
  120.             foreach(var tmp in _ls)  
  121.             {  
  122.                 if (tmp.Score > _findScore)  
  123.                 {  
  124.                     _lsFindScore.Add(tmp);  
  125.                 }  
  126.             }  
  127.             _sw.Stop();  
  128.   
  129.             _lblFunctionCost.First(x => x.Name == "lblFunctionCostFor").Text = "For Cost: " + _sw.Elapsed.TotalMilliseconds.ToString() + " ms    Find count: " + _lsFindScore.Count.ToString();  
  130.   
  131.             if (_lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Count > 0) { _lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Clear(); }  
  132.             foreach (var tmp in _lsFindScore)  
  133.             {  
  134.                 _lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Add("No: " + tmp.No.ToString() + " Name: " + tmp.Name + " Score: " + tmp.Score);  
  135.             }  
  136.         }  
  137.   
  138.         private void FunctionFindAll(List<DataClass> _ls, int _findScore)  
  139.         {  
  140.             if (_ls == null) { MessageBox.Show("The data list is null so will return FunctionForEach"); return; }  
  141.   
  142.             _lsFindScore = new List<DataClass>();  
  143.             _sw = new Stopwatch();  
  144.             _sw.Reset();  
  145.             _sw.Start();  
  146.             _lsFindScore = _lsData.FindAll(x => x.Score > _findScore).ToList();  
  147.             _sw.Stop();  
  148.   
  149.             _lblFunctionCost.First(x => x.Name == "lblFunctionCostFind").Text = "FindAll Cost: " + _sw.Elapsed.TotalMilliseconds.ToString() + " ms    Find count: " + _lsFindScore.Count.ToString();  
  150.   
  151.             if (_lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Count > 0) { _lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Clear(); }  
  152.             foreach (var tmp in _lsFindScore)  
  153.             {  
  154.                 _lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Add("No: " + tmp.No.ToString() + " Name: " + tmp.Name + " Score: " + tmp.Score);  
  155.             }  
  156.         }  
  157.   
  158.         private void FunctionLinq(List<DataClass> _ls, int _findScore)  
  159.         {  
  160.             if (_ls == null) { MessageBox.Show("The data list is null so will return FunctionForEach"); return; }  
  161.   
  162.             _lsFindScore = new List<DataClass>();  
  163.             _sw = new Stopwatch();  
  164.             _sw.Reset();  
  165.             _sw.Start();  
  166.             _lsFindScore =  
  167.                 (from tmp in _lsData  
  168.                 where tmp.Score > _findScore  
  169.                 select tmp).ToList();  
  170.             _sw.Stop();  
  171.   
  172.             _lblFunctionCost.First(x => x.Name == "lblFunctionCostLinq").Text = "LinqSelect Cost: " + _sw.Elapsed.TotalMilliseconds.ToString() + " ms    Find count: " + _lsFindScore.Count.ToString();  
  173.   
  174.             if (_lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Count > 0) { _lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Clear(); }  
  175.             foreach (var tmp in _lsFindScore)  
  176.             {  
  177.                 _lsbDataInfo.First(x => x.Name == "lsbFindData").Items.Add("No: " + tmp.No.ToString() + " Name: " + tmp.Name + " Score: " + tmp.Score);  
  178.             }  
  179.         }  
  180.  
  181.         #region Create UI  
  182.   
  183.         private void CreateButtonWithUI()  
  184.         {  
  185.             _btnUITest = new Button();  
  186.             _btnUITest.Name = "btnUITest";  
  187.             _btnUITest.Text = "UI Test";  
  188.             _btnUITest.Location = new Point(this.Width - 100, this.Height - 100);  
  189.             _btnUITest.Click += btnUITest_Click;  
  190.   
  191.             this.Controls.Add(_btnUITest);  
  192.         }  
  193.   
  194.         private void CreateButtonWithFunction(int _total)  
  195.         {  
  196.             _btnFunction = new Button[_total];  
  197.             for (int i = 0; i<_total;i++)  
  198.             {  
  199.                 _btnFunction[i] = new Button();  
  200.                 switch(i)  
  201.                 {  
  202.                     case 0:  
  203.                         _btnFunction[i].Name = "btnFunctionData";  
  204.                         _btnFunction[i].Text = "Reset Data";  
  205.                         _btnFunction[i].Size = new Size(100, 20);  
  206.                         _btnFunction[i].Location = new Point(20, 20);  
  207.                         _btnFunction[i].Click += btnFunction_Click;  
  208.   
  209.                         break;  
  210.                     case 1:  
  211.                         _btnFunction[i].Name = "btnFunctionFor";  
  212.                         _btnFunction[i].Text = "For Each";  
  213.                         _btnFunction[i].Size = new Size(100, 20);  
  214.                         _btnFunction[i].Location = new Point(20, 50);  
  215.                         _btnFunction[i].Click += btnFunction_Click;  
  216.   
  217.                         break;  
  218.                     case 2:  
  219.                         _btnFunction[i].Name = "btnFunctionFind";  
  220.                         _btnFunction[i].Text = "Find All";  
  221.                         _btnFunction[i].Size = new Size(100, 20);  
  222.                         _btnFunction[i].Location = new Point(20, 80);  
  223.                         _btnFunction[i].Click += btnFunction_Click;  
  224.   
  225.                         break;  
  226.                     case 3:  
  227.                         _btnFunction[i].Name = "btnFunctionLinq";  
  228.                         _btnFunction[i].Text = "Linq Select";  
  229.                         _btnFunction[i].Size = new Size(100, 20);  
  230.                         _btnFunction[i].Location = new Point(20, 110);  
  231.                         _btnFunction[i].Click += btnFunction_Click;  
  232.                           
  233.                         break;  
  234.                 }  
  235.   
  236.                 this.Controls.Add(_btnFunction[i]);  
  237.             }  
  238.         }  
  239.   
  240.         private void CreateLabelWithFunctionCost(int _total)  
  241.         {  
  242.             _lblFunctionCost = new Label[_total];  
  243.             for (int i = 0; i<_total;i++)  
  244.             {  
  245.                 _lblFunctionCost[i] = new Label();  
  246.                 switch(i)  
  247.                 {  
  248.                     case 0:  
  249.                         _lblFunctionCost[i].Name = "lblFunctionCostFor";  
  250.                         _lblFunctionCost[i].Text = "For Cost: ";  
  251.                         _lblFunctionCost[i].Location = new Point(140, 50);  
  252.                         _lblFunctionCost[i].Size = new Size(300, 20);  
  253.   
  254.                         break;  
  255.                     case 1:  
  256.                         _lblFunctionCost[i].Name = "lblFunctionCostFind";  
  257.                         _lblFunctionCost[i].Text = "FindAll Cost: ";  
  258.                         _lblFunctionCost[i].Location = new Point(140, 80);  
  259.                         _lblFunctionCost[i].Size = new Size(300, 20);  
  260.   
  261.                         break;  
  262.                     case 2:  
  263.                         _lblFunctionCost[i].Name = "lblFunctionCostLinq";  
  264.                         _lblFunctionCost[i].Text = "LinqSelect Cost: ";  
  265.                         _lblFunctionCost[i].Location = new Point(140, 110);  
  266.                         _lblFunctionCost[i].Size = new Size(300, 20);  
  267.   
  268.                         break;  
  269.                     case 3:  
  270.                         _lblFunctionCost[i].Name = "lblOriginalData";  
  271.                         _lblFunctionCost[i].Text = "Original Data: ";  
  272.                         _lblFunctionCost[i].Location = new Point(20, 140);  
  273.                         _lblFunctionCost[i].Size = new Size(200, 20);  
  274.   
  275.                         break;  
  276.                     case 4:  
  277.                         _lblFunctionCost[i].Name = "lblFindData";  
  278.                         _lblFunctionCost[i].Text = "Find Data: ";  
  279.                         _lblFunctionCost[i].Location = new Point(310, 140);  
  280.                         _lblFunctionCost[i].Size = new Size(200, 20);  
  281.   
  282.                         break;  
  283.                     case 5:  
  284.                         _lblFunctionCost[i].Name = "lblScore";  
  285.                         _lblFunctionCost[i].Text = "Find Score: ";  
  286.                         _lblFunctionCost[i].Location = new Point(310, 20);  
  287.                         _lblFunctionCost[i].Size = new Size(100, 20);  
  288.   
  289.                         break;  
  290.                 }  
  291.   
  292.                 this.Controls.Add(_lblFunctionCost[i]);  
  293.             }  
  294.         }  
  295.   
  296.         private void CreateNumbericUpDown(int _total)  
  297.         {  
  298.             _nudDataNumber = new NumericUpDown[_total];  
  299.             for (int i = 0;i<_total;i++)  
  300.             {  
  301.                 _nudDataNumber[i] = new NumericUpDown();  
  302.                 switch (i)  
  303.                 {  
  304.                     case 0:  
  305.                         _nudDataNumber[i].Name = "nudDataCount";  
  306.                         _nudDataNumber[i].Value = 10;  
  307.                         _nudDataNumber[i].Size = new Size(50, 20);  
  308.                         _nudDataNumber[i].Location = new Point(140, 20);  
  309.                         _nudDataNumber[i].Minimum = 0;  
  310.                         _nudDataNumber[i].Maximum = 9999;  
  311.                         _nudDataNumber[i].Increment = 1;  
  312.   
  313.                         break;  
  314.                     case 1:  
  315.                         _nudDataNumber[i].Name = "nudScore";  
  316.                         _nudDataNumber[i].Value = 10;  
  317.                         _nudDataNumber[i].Size = new Size(50, 20);  
  318.                         _nudDataNumber[i].Location = new Point(410, 20);  
  319.                         _nudDataNumber[i].Minimum = 0;  
  320.                         _nudDataNumber[i].Maximum = 100;  
  321.                         _nudDataNumber[i].Increment = 1;  
  322.   
  323.                         break;  
  324.                 }  
  325.   
  326.                 this.Controls.Add(_nudDataNumber[i]);  
  327.             }  
  328.         }  
  329.   
  330.         private void CreateListbox(int _total)  
  331.         {  
  332.             _lsbDataInfo = new ListBox[_total];  
  333.             for (int i = 0; i<_total;i++)  
  334.             {  
  335.                 _lsbDataInfo[i] = new ListBox();  
  336.                 switch(i)  
  337.                 {  
  338.                     case 0:  
  339.                         _lsbDataInfo[i].Name = "lsbOriginalData";  
  340.                         _lsbDataInfo[i].Location = new Point(20, 160);  
  341.                         _lsbDataInfo[i].Size = new Size(250, 400);  
  342.   
  343.                         break;  
  344.                     case 1:  
  345.                         _lsbDataInfo[i].Name = "lsbFindData";  
  346.                         _lsbDataInfo[i].Location = new Point(310, 160);  
  347.                         _lsbDataInfo[i].Size = new Size(250, 400);  
  348.   
  349.                         break;  
  350.                 }  
  351.   
  352.                 this.Controls.Add(_lsbDataInfo[i]);  
  353.             }  
  354.         }  
  355.  
  356.         #endregion // Create UI  
  357.  
  358.         #endregion Private Function  
  359.  
  360.         #endregion // Function  
  361.   
  362.     }  
  363.   
  364.     public class DataClass  
  365.     {  
  366.         public int No { getset; }  
  367.         public string Name { getset; }  
  368.         public int Score { getset; }  
  369.   
  370.         public DataClass(int _no, string _name, int _score)  
  371.         {  
  372.             No = _no;  
  373.             Name = _name;  
  374.             Score = _score;  
  375.         }  
  376.     }  
  377. }  



沒有留言:

張貼留言