排序&比對&查找

  • 62
  • 0
  • 2023-08-02

OrderBy(), ThenBy() , 空白在下方的遞增排序, IComparable, IComparer, Comparer, BinarySearch, IndexOf, CompareTo

CompareTo
string s1 = "a";
string s2 = "b";
Response.Write(s1.CompareTo(s2)); //-1

string a = "1";
string b = "2";
Console.log(a.CompareTo(b)); //-1

string a = "1";
string b = "1";
Console.log(a.CompareTo(b)); //0

string a = "2";
string b = "1";
Console.log(a.CompareTo(b)); //1
//linq to sql
.Where(x => x.ColumnOne.CompareTo(x.ColumnTwo) <= 0)
結果等同
//sql
where ColumnOne <= ColumnTwo
CompareTo vs (equal or ==)
官網說明功能目的不同, 不適合做相同比對

官網說明: https://learn.microsoft.com/en-us/dotnet/api/system.string.compareto?view=net-7.0

The CompareTo method was designed primarily for use in sorting or alphabetizing operations. 

It should not be used when the primary purpose of the method call is to determine whether two strings are equivalent. 

To determine whether two strings are equivalent, call the Equals method.

參考文章: https://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c-sharp

非英數字的比對
用Equals引用StringComparison比對, 可排除因文化特性的差異

參考文章: https://stackoverflow.com/questions/23720956/same-chinese-text-not-passing-equality-test

Array.BinarySearch vs IndexOf

https://stackoverflow.com/questions/34969585/which-one-is-faster-binarysearch-or-indexof

BinarySearch: o(log n)
IndexOf: o(n)

https://medium.com/@nathanbell09/binary-search-vs-indexof-63651f91acb7

依[資料量]及[是否已排序]決定
- 資料量少,用IndexOf不一定慢
- 資料量大,是否已排序決定,若資料量大且未排序,BinarySearch要先排序才查找
IComparable vs IComparer: https://stackoverflow.com/questions/5980780/difference-between-icomparable-and-icomparer
IComparable: 表明此物件可比較, 在物件裡實作CompareTo()
指定要比較的屬性及條件, 並將比較對象傳入比較
class T : IComparable<T>
{
    public int CompareTo(T other)
    {
        //比較的屬性及條件
    }
}
IComparer:   主要用在多筆資料的排序, 另外實作物件後
傳入可吃Comparison<T>的Sort等排序

class HeightComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return x.Height- y.Height;
    }
}

people.Sort(p, new HeightComparer()); 
IComparer vs Comparer: https://stackoverflow.com/questions/26698497/should-we-extend-comparert-or-implement-icomparert
OrderBy()後ThenBy() 
原始資料OrderBy(1)OrderBy(1)後OrderBy(2):只排第2欄位的結果OrderBy(1)後ThenBy(2):依第1欄位有重覆的,再排第2欄位
3 2
7 3
4 9
4 0
6 5
3 2
4 9
4 0
6 5
7 3
4 0
3 2
7 3
6 5
4 9
3 2
4 0
4 9
6 5
7 3
劇本:做遞增排序且空白排在後面
原始資料目標排序結果直接OrderBy()
2020/3/8
2019/4/7
(空白)
2020/10/8
(空白)
2019/4/7
2020/3/8
2020/10/8
(空白)
(空白)
(空白)
(空白)
2019/4/7
2020/3/8
2020/10/8
參考解法
DataTable orderedTable = source.AsEnumerable()
                       .OrderByDescending(row => !string.IsNullOrWhiteSpace(row.Field<string>("colName")))
                       .ThenBy(row => row.Field<string>("colName"))
                       .CopyToDataTable();

This will place null values at the end of the table (note that both empty and white spaces strings will have the same rank) and then order the requested column in ascending order.