Cái này em chỉ mới làm chiều nay thôi, còn ai đã từng hỏi thì em chưa biết. Vậy sẳn bài này, Thầy đưa cái bài Thầy đã làm để tham khảo luôn đi Thầy nhé!
Làm đại 2 cách cách nào được thì lấy .
Phương án 1
PHP:
Function Function1(Str As String) As String
Dim Arr, i As Long, j As Long, Tmp, Count As Long
Arr = Split(Str, ", ")
For i = LBound(Arr) To UBound(Arr)
For j = i + 1 To UBound(Arr)
If CLng(Arr(j)) < CLng(Arr(i)) Then
Tmp = Arr(j): Arr(j) = Arr(i): Arr(i) = Tmp
End If
Next
Next
Tmp = Arr(LBound(Arr)): Count = 1: Str = ""
For i = LBound(Arr) + 1 To UBound(Arr)
If CLng(Arr(i)) = Tmp + Count Then
Count = Count + 1
Else
Str = Str & ", " & Tmp & IIf(Count > 1, "-" & (Tmp + Count - 1), "")
Tmp = CLng(Arr(i))
Count = 1
End If
Next
Str = Str & ", " & Tmp & IIf(Count > 1, "-" & (Tmp + Count - 1), "")
Function1 = Replace(Str, ", ", "", 1, 1)
End Function
Phương án 2
PHP:
Function Function2(Str As String) As String
Dim Arr, i As Long, j As Long, Tmp, Check As Boolean
On Error Resume Next
Arr = Split(Str, ", ")
For i = LBound(Arr) To UBound(Arr)
For j = i + 1 To UBound(Arr)
If CLng(Arr(j)) < CLng(Arr(i)) Then
Tmp = Arr(j): Arr(j) = Arr(i): Arr(i) = Tmp
End If
Next
If CLng(Arr(i)) = Arr(i - 1) + 1 Then
If Check Then
Arr(i - 1) = ""
Else
Arr(i - 1) = Arr(i - 1) & "-"
Check = True
End If
Else
Arr(i - 1) = Arr(i - 1) & ", "
Check = False
End If
Next
Function2 = Join(Arr, "")
End Function
*Anh ra đề bài như vậy --> chắc là để so sánh giải thuật
*Bài này mà anh đố theo kiểu : không dùng mảng, không dùng vòng lặp , chắc là em potay.com
Em dùng hàm tự tạo sau :
[GPECODE=vb]
Function Umsbala(str$) As String
Dim tmpArr, Arr(0 To 100)
Dim i&, j&, tmp$
tmpArr = Split(str, ",")
For i = 0 To UBound(tmpArr)
j = tmpArr(i)
Arr(j) = j
Next
For i = 0 To 100
If Len(Arr(i)) Then
For j = i + 1 To 100
If Len(Arr(j)) Then
If Len(Arr(j + 1)) Then
Arr(j) = ""
Else
Arr(j) = "-" & Arr(j) & ","
i = j
Exit For
End If
Else
Arr(i) = Arr(i) & ","
Exit For
End If
Next
End If
Next
tmp = Join(Arr, "")
Umsbala = Left(tmp, Len(tmp) - 1)
End Function
[/GPECODE]
[GPECODE=vb]
Sub Ktr()
MsgBox Umsbala("1, 8, 6, 4, 5, 11, 12, 13, 16, 15, 20, 14, 10, 7")
End Sub
[/GPECODE]
*Anh ra đề bài như vậy --> chắc là để so sánh giải thuật
*Bài này mà anh đố theo kiểu : không dùng mảng, không dùng vòng lặp , chắc là em potay.com
Em dùng hàm tự tạo sau :
Mã:
Function Umsbala(str$) As String
.....
[B]For i = 0 To [COLOR=#ff0000]100[/COLOR][/B]
dạ, số "đo đỏ" >= Max(Slpit(Str,",")) --> ý tưởng của em là sắp xếp mảng tăng dần ,dựa vào chỉ số của một mảng phụ , cụ thể:
*ta có mảng 1,2,10,16,20,4
* xây dựng một mảng phu: Arr(1) = 1, Arr(2) = 2,Arr(3) ="",...Arr(10) =10
* Cách sắp xếp này của em tiết kiệm "được" 1 vòng for..next, nhưng mà "mất" cái gì em cũng không biết
* Như vậy con số "đỏ đỏ"em chọn = 100 vì ví dụ anh nghĩa đưa ra có giả trị các con số < 100,
p/s : em xem lại thấy code em viết quả là "chuối củ "
*Anh ra đề bài như vậy --> chắc là để so sánh giải thuật
*Bài này mà anh đố theo kiểu : không dùng mảng, không dùng vòng lặp , chắc là em potay.com
Em dùng hàm tự tạo sau :
[GPECODE=vb]
Function Umsbala(str$) As String
Dim tmpArr, Arr(0 To 100)
Dim i&, j&, tmp$
tmpArr = Split(str, ",")
For i = 0 To UBound(tmpArr)
j = tmpArr(i)
Arr(j) = j
Next
For i = 0 To 100
If Len(Arr(i)) Then
For j = i + 1 To 100
If Len(Arr(j)) Then
If Len(Arr(j + 1)) Then
Arr(j) = ""
Else
Arr(j) = "-" & Arr(j) & ","
i = j
Exit For
End If
Else
Arr(i) = Arr(i) & ","
Exit For
End If
Next
End If
Next
tmp = Join(Arr, "")
Umsbala = Left(tmp, Len(tmp) - 1)
End Function
[/GPECODE]
[GPECODE=vb]
Sub Ktr()
MsgBox Umsbala("1, 8, 6, 4, 5, 11, 12, 13, 16, 15, 20, 14, 10, 7")
End Sub
[/GPECODE]
Ý tưởng của bạn cũng rất hay đấy, nếu sửa lại một chút là được, dùng cho trường hợp lược duy nhất:
Mã:
Function Umsbala(str$) As String
Dim tmpArr, [COLOR=#ff0000]Arr()[/COLOR], [COLOR=#0000cd]iMax As Long[/COLOR]
Dim i&, j&
tmpArr = Split(str, ",")
For i = 0 To UBound(tmpArr)
j = tmpArr(i)
[COLOR=#0000cd] If j > iMax Then iMax = j[/COLOR]
[COLOR=#ff0000] ReDim Preserve Arr(0 To iMax)[/COLOR]
Arr(j) = j
Next
For i = 0 To [COLOR=#0000cd]iMax[/COLOR]
If Len(Arr(i)) Then
For j = i + 1 To [COLOR=#0000cd]iMax[/COLOR]
If Len(Arr(j)) Then
If Len(Arr(j + 1)) Then
Arr(j) = ""
Else
Arr(j) = "-" & Arr(j) & ","
i = j
Exit For
End If
Else
Arr(i) = Arr(i) & ","
Exit For
End If
Next
End If
Next
[COLOR=#0000cd] Umsbala = Join(Arr, "")[/COLOR]
End Function
Đúng là như thế, nhưng nếu bạn làm như thế thì Thầy NDU chả phải góp ý cho bạn đâu hen. Cái hay của topic này là như vậy, đố để giải, giải để học, học qua học lại từ đó tất cả đều được học và đều tiến bộ là như thế đó.
Nếu có số trùng thì cả 2 code của tôi đang thực hiện theo hướng thứ 2. Còn nếu loại bỏ số trùng thì cũng đơn giản. Trong quá trình sắp xếp lại mảng, cái nào trùng thì bỏ ra. Ta sẽ được mảng duy nhất.
Nếu có số trùng thì cả 2 code của tôi đang thực hiện theo hướng thứ 2. Còn nếu loại bỏ số trùng thì cũng đơn giản. Trong quá trình sắp xếp lại mảng, cái nào trùng thì bỏ ra. Ta sẽ được mảng duy nhất.
Với bài này tôi muốn các bạn vận dụng CreateObject("MSScriptControl.ScriptControl") để sắp xếp dãy số, tuy nó chẳng mới mẽ gì, nhưng ít thấy ai sử dụng, nó không có vòng lặp nào cả, nhưng đảm bảo sắp xếp không sai tí nào cả. Còn ta dùng vòng lặp, chưa chắc đã đúng hết hoặc dùng rất nhiều vòng lặp để thực hiện.
Sau khi dùng nó, ta chỉ cần duyệt các số qua thêm 1 vòng lặp nữa thôi thì công việc đã hoàn tất rồi.
Đây là đáp án của mình:
[GPECODE=vb]
Function SummarySerries(ByVal SerStr As String, Optional ByVal Unique As Boolean = True) As String
Dim StrSplit As Variant, _
i As Long, LenTmp As Long, _
Item As String, Tmp As String
SerStr = Replace(SerStr, " ", "")
''SAP XEP LAI DAY SO TU NHO DEN LON:
SerStr = "('" & SerStr & "').split(',').sort(function(a,b){return(a-b)}).join(',')"
With CreateObject("MSScriptControl.ScriptControl")
.Language = "JavaScript"
StrSplit = Split(.Eval(SerStr), ",")
End With
If Unique Then
''LUOC SO DUY NHAT:
For i = 0 To UBound(StrSplit)
Item = StrSplit(i)
If Item <> Tmp Then
If Tmp = "" Then
SummarySerries = SummarySerries & Item
Else
If Item - Tmp = 1 Then
SummarySerries = Replace(SummarySerries, "-" & Tmp, "") & "-" & Item
Else
SummarySerries = SummarySerries & ", " & Item
End If
End If
End If
Tmp = Item
Next
Else
''LUOC SO VAN DUY TRI SO TRUNG:
For i = 0 To UBound(StrSplit)
Item = StrSplit(i)
If Tmp = "" Then
SummarySerries = SummarySerries & Item
Else
If Item - Tmp = 1 Then
If InStr(Right(SummarySerries, Len(Tmp) + 1), "-") Then
LenTmp = Len(SummarySerries) - Len(Tmp) - 1
SummarySerries = Left(SummarySerries, LenTmp) & "-" & Item
Else
SummarySerries = SummarySerries & "-" & Item
End If
Else
SummarySerries = SummarySerries & ", " & Item
End If
End If
Tmp = Item
Next
End If
End Function
[/GPECODE]
Thủ tục:
Mã:
Sub XulyDaySo()
Dim SerStr As String
SerStr = "1,9,1,2,1,8,16,,,,4,3,11,11,9 ,,, ,5,11,12,13,,,,16,15,20,15,14,10,7,20"
Debug.Print SummarySerries(SerStr) 'Luoc duy nhat
Debug.Print SummarySerries(SerStr, 0) 'Khong duy nhat
End Sub
Function SummarySerries(ByVal SerStr As String, Optional ByVal Unique As Boolean = True) As String
Dim StrSplit As Variant, _
i As Long, LenTmp As Long, _
Item As String, Tmp As String
SerStr = Replace(SerStr, " ", "")
''SAP XEP LAI DAY SO TU NHO DEN LON:
SerStr = "('" & SerStr & "').split(',').sort(function(a,b){return(a-b)}).join(',')"
With CreateObject("MSScriptControl.ScriptControl")
.Language = "JavaScript"
StrSplit = Split(.Eval(SerStr), ",")
End With
1 like cho Đoạn code : sắp xếp các số trong chuỗi từ lớn đến nhỏ, không cần dùng vòng lặp !
--> <---
Nhưng mà tại sao em gõ createObject("MSScriptControl.ScriptControl") --> lỗi ActiveX components can't create object
--> điều kiện sử dụng là gì vậy anh ? em dùng win 8 64 bits
Cũng lạ thật, mặc dù em References vào microsoft script control 1.0 và sửa thành "with new scriptcontrol" mà vẫn báo lỗi
không lẽ là do cái thằng script control này đang nằm ở thư mục C:\Window\sýsWOW64\mmscript.ocx
1 like cho Đoạn code : sắp xếp các số trong chuỗi từ lớn đến nhỏ, không cần dùng vòng lặp !
--> <---
Nhưng mà tại sao em gõ createObject("MSScriptControl.ScriptControl") --> lỗi ActiveX components can't create object
--> điều kiện sử dụng là gì vậy anh ? em dùng win 8 64 bits
vì Ram em 4G nên em mới cài 64 bits, em vừa ktra : win 64 là C:\Window\sýsWOW64\mmscript.ocx, còn 32 bits hình như là C:\Window\system32\mmscript.ocx , để em google thử xem ntn ?
ặc vừa search đã thấy : [NOTE1]The msscript component was not ported to 64 bit. It's a legacy component and MS chose not to put the effort into migrating it to 64 bit. You'll simply need to find another way to do whatever it is you do with that component.[/NOTE1]
Translate google : [NOTE1]Thành phần msscript không được chuyển đến 64 bit. Đó là một phần di sản và MS đã quyết định không đặt các nỗ lực vào di chuyển nó đến 64 bit. Bạn chỉ đơn giản là sẽ cần phải tìm một cách khác để làm bất cứ điều gì bạn làm với thàn[/NOTE1]
** Lại phải suy nghĩ về vụ Ram 4G nên cài 32 bits hay 64 bits và hình như cả DAO cũng không chạy trên 64bits !
vì Ram em 4G nên em mới cài 64 bits, em vừa ktra : win 64 là C:\Window\sýsWOW64\mmscript.ocx, còn 32 bits hình như là C:\Window\system32\mmscript.ocx , để em google thử xem ntn ?
[NOTE1]----- Original Message -----From: "Doug Lee" <doug.lee@xxxxxxxxxxxxxxxx>
To: <jawsscripts@xxxxxxxxxxxxx>
Sent: Saturday, April 20, 2013 11:54 PM
Subject: [jawsscripts] Re: CreateObject on 64 bit sistem
CreateObject functions should be able to work on 64-bit Windows, but you would need a 64-bit version of the object you want, I think. Some objects don't come in that flavor. For example, the MSScriptControl.ScriptControl object was, to my knowledge, never made available in a 64-bit environment.
On Sat, Apr 20, 2013 at 11:51:09PM +0200, Dragan Miljojcic wrote:
Hello,
Has anyone successfully used the Jaws function "CreateObjectEx" on a 64 bit system. It seems that Jaws14 on 64 bit system, do not create an object, while the same Jaws script works on 32 bit system. Do you have any experience with this. I will be very grateful for any response.
Với bài này tôi muốn các bạn vận dụng CreateObject("MSScriptControl.ScriptControl") để sắp xếp dãy số, tuy nó chẳng mới mẽ gì, nhưng ít thấy ai sử dụng, nó không có vòng lặp nào cả,
Sau khi dùng nó, ta chỉ cần duyệt các số qua thêm 1 vòng lặp nữa thôi thì công việc đã hoàn tất rồi.
Thế nếu bạn hungpecc1 sửa lại chút code rồi viết thành DLL nào đó rồi sau đó tôi dùng SUB của bạn ấy thì sao? Chả nhẽ tôi sẽ nói: "không dùng vòng lặp"? Thậm chí tôi còn hét lên: Thậm chí không cần "chỉ cần duyệt các số qua thêm 1 vòng lặp nữa thôi thì công việc đã hoàn tất rồi" mà có luôn "công việc đã hoàn tất"?
Nếu công việc bắt buộc phải "đóng đinh" thì phải đóng đinh, thế thôi. Bạn không phải đóng đinh chẳng qua là bạn "mượn" ai đó đóng định hộ bạn mà thôi. Cũng có thể bạn và không ai đóng định nhưng lúc đó thì để làm công việc bạn phải "vặn vít". Bạn không vặn thì có nghĩa là bạn "mượn" ai đó vặn. Mà bạn đừng khoe là không phải đóng đinh nhé. Vì lúc đó tôi sẽ khoe là tôi không phải vặn vít như bạn.
Công việc không tự nhiên sinh ra và cũng không tự nhiên mất đi. Nó chỉ "nhẩy" từ người này sang người khác. Bạn học định luật bảo toàn công việc chưa? He he.
Tôi không hiểu bạn khoe cái "không dùng vòng lặp" để làm gì nhỉ? Một đằng là tự viết, một đằng là dùng "đồ" của người khác.
Thế nếu bạn hungpecc1 sửa lại chút code rồi viết thành DLL nào đó rồi sau đó tôi dùng SUB của bạn ấy thì sao? Chả nhẽ tôi sẽ nói: "không dùng vòng lặp"? Thậm chí tôi còn hét lên: Thậm chí không cần "chỉ cần duyệt các số qua thêm 1 vòng lặp nữa thôi thì công việc đã hoàn tất rồi" mà có luôn "công việc đã hoàn tất"?
Nếu công việc bắt buộc phải "đóng đinh" thì phải đóng đinh, thế thôi. Bạn không phải đóng đinh chẳng qua là bạn "mượn" ai đó đóng định hộ bạn mà thôi. Cũng có thể bạn và không ai đóng định nhưng lúc đó thì để làm công việc bạn phải "vặn vít". Bạn không vặn thì có nghĩa là bạn "mượn" ai đó vặn. Mà bạn đừng khoe là không phải đóng đinh nhé. Vì lúc đó tôi sẽ khoe là tôi không phải vặn vít như bạn.
Công việc không tự nhiên sinh ra và cũng không tự nhiên mất đi. Nó chỉ "nhẩy" từ người này sang người khác. Bạn học định luật bảo toàn công việc chưa? He he.
Đã nói không dùng vòng lặp trong VBA rồi mà Thầy, thử xem, nếu dùng hàm InStr để tìm 1 hoặc nhiều ký tự nào đó trong một chuỗi, thì bản thân nó có dùng vòng lặp không? Ai đảm bảo rằng nó sẽ không có đằng sau "hậu trường"? Tuy nhiên, khi người sử dụng nó, có quyền nói rằng "tôi không dùng vòng lặp" trong code của tôi. Vậy thôi à.
Đã nói không dùng vòng lặp trong VBA rồi mà Thầy, thử xem, nếu dùng hàm InStr để tìm 1 hoặc nhiều ký tự nào đó trong một chuỗi, thì bản thân nó có dùng vòng lặp không? Ai đảm bảo rằng nó sẽ không có đằng sau "hậu trường"? Tuy nhiên, khi người sử dụng nó, có quyền nói rằng "tôi không dùng vòng lặp" trong code của tôi. Vậy thôi à.
Oh, thật ra em không nhấn mạnh điều này, bởi vì mỗi người có mỗi thuật toán để thực hiện, những người làm đúng yêu cầu thì đã là có đáp án đúng. Điều em mong đợi rằng qua nhiều đáp án, sẽ có nhiều cách để thực hiện yêu cầu đó, thông qua đó, em sẽ được học thêm nhiều.
Kinh nghiệm cho em thấy rằng "Hãy cho rồi sẽ nhận", nên em sẳn sàng gửi tặng những gì em học được và hiểu biết được lên diễn đàn, và sau đó em biết em sẽ được nhiều người góp ý, chỉnh sửa và hoàn thiện ý tưởng của em.
Làm đại 2 cách cách nào được thì lấy .
Phương án 1
PHP:
Function Function1(Str As String) As String
Dim Arr, i As Long, j As Long, Tmp, Count As Long
Arr = Split(Str, ", ")
For i = LBound(Arr) To UBound(Arr)
For j = i + 1 To UBound(Arr)
If CLng(Arr(j)) < CLng(Arr(i)) Then
Tmp = Arr(j): Arr(j) = Arr(i): Arr(i) = Tmp
End If
Next
Next
Tmp = Arr(LBound(Arr)): Count = 1: Str = ""
For i = LBound(Arr) + 1 To UBound(Arr)
If CLng(Arr(i)) = Tmp + Count Then
Count = Count + 1
Else
Str = Str & ", " & Tmp & IIf(Count > 1, "-" & (Tmp + Count - 1), "")
Tmp = CLng(Arr(i))
Count = 1
End If
Next
Str = Str & ", " & Tmp & IIf(Count > 1, "-" & (Tmp + Count - 1), "")
Function1 = Replace(Str, ", ", "", 1, 1)
End Function
Thế nếu bạn hungpecc1 sửa lại chút code rồi viết thành DLL nào đó rồi sau đó tôi dùng SUB của bạn ấy thì sao? Chả nhẽ tôi sẽ nói: "không dùng vòng lặp"? Thậm chí tôi còn hét lên: Thậm chí không cần "chỉ cần duyệt các số qua thêm 1 vòng lặp nữa thôi thì công việc đã hoàn tất rồi" mà có luôn "công việc đã hoàn tất"?
Nếu công việc bắt buộc phải "đóng đinh" thì phải đóng đinh, thế thôi. Bạn không phải đóng đinh chẳng qua là bạn "mượn" ai đó đóng định hộ bạn mà thôi. Cũng có thể bạn và không ai đóng định nhưng lúc đó thì để làm công việc bạn phải "vặn vít". Bạn không vặn thì có nghĩa là bạn "mượn" ai đó vặn. Mà bạn đừng khoe là không phải đóng đinh nhé. Vì lúc đó tôi sẽ khoe là tôi không phải vặn vít như bạn.
Công việc không tự nhiên sinh ra và cũng không tự nhiên mất đi. Nó chỉ "nhẩy" từ người này sang người khác. Bạn học định luật bảo toàn công việc chưa? He he.
Đây là sai lầm ngớ ngẩn nhất của nhiều người sử dụng - cứ tưởng đó không phải dùng vòng lặp (khi sử dụng công cụ khác) - ví như dùng máy xay sinh tốt thay vì dùng dao cắt rùi nghền ... sẽ nghĩ nó không cắt không chém ( có khi còn cắt chém nhiều hơn nhiều năng lượng hơn). Vì thế không thể nói là không dùng vòng lặp dù là Instr hay là scripts nào đó
Vì thế, đôi khi ta cần rèn luyện từ bước cơ bản, và hiểu bản chất của các công cụ chứ không phải nói sai từ như thế dẫn đến nhiều người hiểu lầm
2) Gán mảng đó vào sheet sau khi đổi chiều (Transpose)
3) Dùng công cụ SORT của sheet sắp xếp lại dữ liệu
4) Gán ngược giá trị về mảng rồi chuyển mảng về chuỗi.
Mã:
Sub NoiChuoi()
Dim Chuoi As String, Str As String
Dim SplArr, StrSplArr(), i As Long, u As Long
Chuoi = "10,9,8,5,6,7,8,3,4,6,7,9,10,1,11,33"
SplArr = Split(Chuoi, ",")
u = UBound(SplArr) + 1
With Range("F1").Resize(u)
.Value = WorksheetFunction.Transpose(SplArr)
.Sort [F1], xlAscending
SplArr = .Value
End With
For i = 2 To u
Str = Str & "," & SplArr(i, 1)
Next
Str = SplArr(1, 1) & Str
Debug.Print Str
[COLOR=#008000]' ReDim StrSplArr(1 To u)[/COLOR]
[COLOR=#008000]' For i = 1 To u[/COLOR]
[COLOR=#008000]' StrSplArr(i) = SplArr(i, 1)[/COLOR]
[COLOR=#008000]' Next[/COLOR]
[COLOR=#008000]' Chuoi = Join(StrSplArr, ",")[/COLOR]
[COLOR=#008000]' Debug.Print Chuoi[/COLOR]
End Sub
Nhưng chúng ta phải làm như vậy sao? Nếu mà là hàm thì Sheet ở đâu ra nhỉ? Tạo ra? Lỡ phần tử bên trong lớn hơn số hàng thì sao?
Theo em nếu đã đưa được chuỗi về mảng Arr= Split(str,",") ta có thể dùng các thuật toán sắp xếp mảng thông dụng :
* Cách sắp xếp như của a Huuthang_bd hình như được gọi là Selection Sort
* Theo kiểu Quick Sort thì như vậy :
[GPECODE=vb]
Sub quicksort(subArr(), ByVal L As Long, ByVal U As Long)
Dim i As Long, j As Long
Dim pivot, TG
If L >= U Then Exit Sub
i = L: j = U
pivot = Int(Rnd() * (j - i + 1) + i)
Do
While subArr(i) < subArr(pivot)
i = i + 1
Wend
While subArr(j) > subArr(pivot)
j = j - 1
Wend
If i <= j Then
TG = subArr(i): subArr(i) = subArr(j): subArr(j) = TG
i = i + 1
j = j - 1
End If
Loop Until i > j
quicksort subArr, L, j
quicksort subArr, i, U
End Sub
[/GPECODE]
Kiểm tra :
Mã:
Sub test()
Dim arr()
Dim item
arr = Array(1, 3, 5, 8, 97, 4, 5, 6)
quicksort arr, LBound(arr), UBound(arr)
For Each item In arr
Debug.Print item
Next
End Sub
* Hôm qua mới vọc thêm vụ Distribution count sorting :sắp xếp bằng phép đếm phân phối : Cách thức hoạt động của thuật toán - Ta xây dựng dãy c(1),c(2),...,c(M) trong đó c(i) là số lần xuất hiện của số i trong dãy cần sắp xếp. Vd: Với dãy: 1,5,4,2,1,4,7,5,5,8 thì: c(1)=2; c(2)=1,c(4)=2; c(5)=3; c(7)=1; c(8)=1 - Dựa vào c(i), ta có thể biết được giá trị i sẽ nằm từ vị trí nào đến vị trí nào trong dãy đã sắp xếp: Vd: Với dãy trên sau khi đã sắp xếp là: 1,1,2,4,4,5,5,5,7,8 ++++++++++Giá trị 1 đứng ở vị trí từ 1 -> c(1) [tức từ 1 -> 2] ++++++++++Giá trị 2 đứng ở vị trí từ c(1)+1 -> c(1) + c(2) [tức là từ 3->3] ++++++++++Giá trị i đứng ở vị trí từ c(1)+c(2)+c(3)+...+c(i-1)+1 -> c(1)+c(2)+c(3)+...+c(i-1)+c(i) - Sau đó dựa vào dãy c này ta dựng nên dãy t là dãy đã được sắp xếp từ dãy a và gán dãy t vào dãy a.
Mã:
[COLOR=#000080][FONT=monospace]Private[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Sub[/FONT][/COLOR][COLOR=#444444][FONT=monospace] DistributionCountingSort()[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]Dim[/FONT][/COLOR][COLOR=#444444][FONT=monospace] c(1 [/FONT][/COLOR][COLOR=#000080][FONT=monospace]To[/FONT][/COLOR][COLOR=#444444][FONT=monospace] M) [/FONT][/COLOR][COLOR=#000080][FONT=monospace]As[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Long[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]Dim[/FONT][/COLOR][COLOR=#444444][FONT=monospace] t(1 [/FONT][/COLOR][COLOR=#000080][FONT=monospace]To[/FONT][/COLOR][COLOR=#444444][FONT=monospace] N) [/FONT][/COLOR][COLOR=#000080][FONT=monospace]As[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Long[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]Dim[/FONT][/COLOR][COLOR=#444444][FONT=monospace] i [/FONT][/COLOR][COLOR=#000080][FONT=monospace]As[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Long[/FONT][/COLOR][COLOR=#444444][FONT=monospace], j [/FONT][/COLOR][COLOR=#000080][FONT=monospace]As[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Long[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]For[/FONT][/COLOR][COLOR=#444444][FONT=monospace] i = 1 [/FONT][/COLOR][COLOR=#000080][FONT=monospace]To[/FONT][/COLOR][COLOR=#444444][FONT=monospace] N[/FONT][/COLOR]
[COLOR=#444444][FONT=monospace] c(a(i)) = c(a(i)) + 1 [/FONT][/COLOR][COLOR=#008000][FONT=monospace]'Đếm số lần xuất hiện của giá trị i trong dãy
[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Next[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]For[/FONT][/COLOR][COLOR=#444444][FONT=monospace] i = 2 [/FONT][/COLOR][COLOR=#000080][FONT=monospace]To[/FONT][/COLOR][COLOR=#444444][FONT=monospace] M[/FONT][/COLOR]
[COLOR=#444444][FONT=monospace] c(i) = c(i - 1) + c(i) [/FONT][/COLOR][COLOR=#008000][FONT=monospace]'Tính vị trí cuối của mỗi giá trị trong dãy
[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Next[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]For[/FONT][/COLOR][COLOR=#444444][FONT=monospace] i = N [/FONT][/COLOR][COLOR=#000080][FONT=monospace]To[/FONT][/COLOR][COLOR=#444444][FONT=monospace] 1 [/FONT][/COLOR][COLOR=#000080][FONT=monospace]Step[/FONT][/COLOR][COLOR=#444444][FONT=monospace] -1[/FONT][/COLOR]
[COLOR=#444444][FONT=monospace] j = a(i) [/FONT][/COLOR][COLOR=#008000][FONT=monospace]'Lấy ra giá trị của khóa a(i)
[/FONT][/COLOR][COLOR=#444444][FONT=monospace] t(c(j)) = a(i) [/FONT][/COLOR][COLOR=#008000][FONT=monospace]'biến c(j) sẽ chứa vị trí mà a(i) cần phải ở khi đã được sắp xếp, giá trị này sẽ được đưa vào đúng vị trí trong dãy t
[/FONT][/COLOR][COLOR=#444444][FONT=monospace] c(j) = c(j) - 1 [/FONT][/COLOR][COLOR=#008000][FONT=monospace]'đồng thời giảm giá trị của c(j) xuống 1 đơn vị để những giá trị sau sẽ được thêm vào trước vị trí trên.
[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Next[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]For[/FONT][/COLOR][COLOR=#444444][FONT=monospace] i = 1 [/FONT][/COLOR][COLOR=#000080][FONT=monospace]To[/FONT][/COLOR][COLOR=#444444][FONT=monospace] N[/FONT][/COLOR]
[COLOR=#444444][FONT=monospace] a(i) = t(i) [/FONT][/COLOR][COLOR=#008000][FONT=monospace]'Gán toàn bộ giá trị của dãy t vào dãy a
[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Next[/FONT][/COLOR]
[COLOR=#000080][FONT=monospace]End[/FONT][/COLOR][COLOR=#000080][FONT=monospace]Sub[/FONT][/COLOR]
p/s : mà hình như chủ đề là " đố vui VBA " còn mấy cái vụ này không được gọi là "đố vui" roài , anh có thể rời bài ra topic " vui để đố " để không vi phạm nội quy
Theo em nếu đã đưa được chuỗi về mảng Arr= Split(str,",") ta có thể dùng các thuật toán sắp xếp mảng thông dụng :
* Cách sắp xếp như của a Huuthang_bd hình như được gọi là Selection Sort
* Theo kiểu Quick Sort thì như vậy
.....................
Một mảng được cắt ra từ chuổi thì nó có được bao nhiêu phần tử mà phải "đấu" về tốc độ
Có thể dùng System.Collections.ArrayList cho đơn giản.
Thí nghiệm xem:
Mã:
Sub Test()
Dim str As String, arr, i As Long
str = "10,9,8,5,6,7,8,3,4,6,7,9,10,1,11,33"
arr = Split(str, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(arr): .Add CLng(arr(i)): Next
.Sort: arr = .ToArray
End With
MsgBox Join(arr, "-")
End Sub
p/s : mà hình như chủ đề là " đố vui VBA " còn mấy cái vụ này không được gọi là "đố vui" roài , anh có thể rời bài ra topic " vui để đố " để không vi phạm nội quy
Bạn hãy đưa dữ liệu đầu vào về dạng chuẩn dữ liệu ở bài đầu tiên bạn đố (tức là giữa các số được phân cách nhau bằng một dấu phẩy và một khoản trắng) thì bạn sẽ thấy.
Sub Test()
Dim str As String, arr, i As Long
str = "10,9,8,5,6,7,8,3,4,6,7,9,10,1,11,33"
arr = Split(str, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(arr): .Add CLng(arr(i)): Next
.Sort: arr = .ToArray
End With
MsgBox Join(arr, "-")
End Sub
Function SortArraySystem2(SerStr As String) As String
Dim str As String, arr, i As Long
arr = Split(SerStr, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(arr)
.Add CLng(arr(i))
Next
.Sort
[COLOR=#ff0000][B] .Reverse[/B][/COLOR]
arr = .ToArray
End With
SortArraySystem2 = Join(arr, "-")
End Function
Một mảng được cắt ra từ chuổi thì nó có được bao nhiêu phần tử mà phải "đấu" về tốc độ
Có thể dùng System.Collections.ArrayList cho đơn giản.
Thí nghiệm xem:
Mã:
Sub Test()
Dim str As String, arr, i As Long
str = "10,9,8,5,6,7,8,3,4,6,7,9,10,1,11,33"
arr = Split(str, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(arr): .Add CLng(arr(i)): Next
.Sort: arr = .ToArray
End With
MsgBox Join(arr, "-")
End Sub
------------------------------
ĐỐ VUI tức là ĐỐ cái gì thật ĐƠN GIẢN nhưng ít ai nghĩ ra (đáp án bất ngờ)
Vậy nên bài này chẳng VUI tí nào
Function SortArrayScript(SerStr As String) As String
SerStr = "('" & SerStr & "').split(',').sort(function(a,b){return (a-b)}).join(',')" ' & ".reverse()" 'if DESC
With CreateObject("MSScriptControl.ScriptControl")
.Language = "JavaScript"
SortArrayScript = .Eval(SerStr)
End With
End Function
Function SortArraySystem(SerStr As String) As String
Dim str As String, arr, i As Long
arr = Split(SerStr, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(arr)
.Add CLng(arr(i))
Next
.Sort: arr = .ToArray
End With
SortArraySystem = Join(arr, "-")
End Function
Xét về tốc độ, thì 2 thằng em này cũng ngang ngang nhau, nếu dùng For ... Next do mình xử lý chuỗi thì có mà chờ dài cổ, tôi đã thử code của huuthang_bd với 1,000 mục cho ra thời gian đâu có bao nhiêu: 114 giây! Trong khi đó, với 60,000 mục thì 2 thằng em trên xử lý trong vòng 2 giây.
Thế cho nên đừng ai vỗ ngực xưng tên tôi hay và chê người ta ngớ ngẫn, mà hãy học thêm và biết chọn lọc tinh hoa của người khác mà ứng dụng vô công việc của mình. Bạn có giỏi thì cứ cắt bằng tay đi rồi nghiền nát, còn tôi thì dùng máy xay sinh tố vậy!
''===================================
Suy cho cùng thì tôi thích cách mà Thầy NDU giới thiệu hơn: System.Collections.ArrayList
Nó dễ hiểu, dễ hình dung, nó đơn giản và không cầu kỳ, không như MSScriptControl.ScriptControl cấu trúc thật sự khó hiểu và không thân thiện lắm.
Thế cho nên đừng ai vỗ ngực xưng tên tôi hay và chê người ta ngớ ngẫn, mà hãy học thêm và biết chọn lọc tinh hoa của người khác mà ứng dụng vô công việc của mình. Bạn có giỏi thì cứ cắt bằng tay đi rồi nghiền nát, còn tôi thì dùng máy xay sinh tố vậy!
Function Sort1DArray(ByVal SourceArray, ByVal Order As Boolean)
Dim i As Long, aTmp
On Error Resume Next
aTmp = SourceArray
With CreateObject("System.Collections.ArrayList")
For i = LBound(aTmp) To UBound(aTmp): .Add aTmp(i): Next
.Sort
If Order = False Then .Reverse
Sort1DArray = .ToArray()
End With
End Function
Function Sort1DArray(ByVal SourceArray, ByVal Order As Boolean)
Dim i As Long, aTmp
On Error Resume Next
aTmp = SourceArray
With CreateObject("System.Collections.ArrayList")
For i = LBound(aTmp) To UBound(aTmp): .Add aTmp(i): Next
.Sort
If Order = False Then .Reverse
Sort1DArray = .ToArray()
End With
End Function
Sẳn đây em cũng có tham khảo một số thủ tục mà CreateObject("System.Collections.ArrayList") hoạt động, những bạn chưa biết nhiều về nó thì tham khảo chung luôn:
[GPECODE=vb] Option Explicit
Sub ptest()
'http://www.robvanderwoude.com/vbstech.php#Data
'http://www.thecodecage.com/forumz/showthread.php?p=1055000938#post1055000938
'this code creates and populates an ArrayList
Dim myArrayList As Object, myArrayList2 As Object
Dim xItem, myrange
'result to immediate window
Debug.Print Join(myArrayList.toarray(), Chr(10))
' copy / clone ArrayList
Set myArrayList2 = myArrayList.Clone
'Now, to add an element and sort the ArrayList, all we need to do is:
'add the new element to the ArrayList
myArrayList.Add "Z"
'remove the new element to the ArrayList
myArrayList.Remove "C"
'result to immediate window
Debug.Print Join(myArrayList.toarray(), Chr(10))
'result to immediate window
Debug.Print "List Has C " & myArrayList.Contains("C")
Debug.Print "List Has Z " & myArrayList.Contains("Z")
'result to immediate window - count elements and capacity
Debug.Print "Size : " & myArrayList.Count
Debug.Print "Capacity : " & myArrayList.Capacity
'trim blank elements from the ArrayList
myArrayList.TrimToSize
'result to immediate window - count elements and capacity
Debug.Print "Size : " & myArrayList.Count
Debug.Print "Capacity : " & myArrayList.Capacity
'sort the ArrayList
myArrayList.Sort
'result to immediate window
Debug.Print Join(myArrayList.toarray(), Chr(10))
' reverse the ArrayList
myArrayList.Reverse
'result to immediate window
Debug.Print Join(myArrayList.toarray(), Chr(10))
' copy / clone ArrayList2 result to immediate window
Debug.Print Join(myArrayList2.toarray(), Chr(10))
'toarray transfer ArrayList to results to worksheet
Range("B1").Resize(myArrayList.Count) = Application.Transpose(myArrayList.toarray())
Range("C1").Resize(1, myArrayList.Count) = myArrayList.toarray()
Set myArrayList = Nothing
Set myArrayList2 = Nothing
End Sub[/GPECODE]
Debug.Print "Size : " & objSortedList.Count
Debug.Print "Capacity : " & objSortedList.Capacity
'This will result in the following output:
'Size : 4
'Capacity : 16
'Size : 4
'Capacity : 4
'Cloning a SortedList is a piece of cake:
Dim xxxx
Set objList2 = objSortedList.Clone
Debug.Print "Sorted List Key(1) = " & objSortedList.GetKey(1)
Debug.Print "Cloned List Key(1) = " & objList2.GetKey(1)
'The result:
'Sorted List Key(1) = Fourth
'Cloned List Key(1) = Fourth
Set objList2 = Nothing
Set objSortedList = Nothing
End Sub [/GPECODE]
[GPECODE=vb]Option Explicit Sub System_Collections_ArrayList()
' Reference Library mscorlib
Dim ArrayListOne As Object, ArrayListTwo As ArrayList, ArrayListThree As Object, ArrayListFour As ArrayList
Set ArrayListOne = CreateObject("System.Collections.ArrayList") ' method with out Reference library
Set ArrayListTwo = New ArrayList 'Can use this method after loading Reference Library mscorlib
Set ArrayListThree = CreateObject("System.Collections.ArrayList") ' method with out Reference library
Set ArrayListFour = New ArrayList 'Can use this method after loading Reference Library mscorlib
Thế cho nên đừng ai vỗ ngực xưng tên tôi hay và chê người ta ngớ ngẫn, mà hãy học thêm và biết chọn lọc tinh hoa của người khác mà ứng dụng vô công việc của mình. Bạn có giỏi thì cứ cắt bằng tay đi rồi nghiền nát, còn tôi thì dùng máy xay sinh tố vậy!
Thế cho nên đừng ai vỗ ngực xưng tên tôi hay và chê người ta ngớ ngẫn, mà hãy học thêm và biết chọn lọc tinh hoa của người khác mà ứng dụng vô công việc của mình. Bạn có giỏi thì cứ cắt bằng tay đi rồi nghiền nát, còn tôi thì dùng máy xay sinh tố vậy!
......
Tôi đã nói ở bài #813 là nói về nhận định của bác siwtom, bạn đừng có chen ngang vào nhé
Nhưng bạn đã cố tình viết, thì tôi trả lời:
Không đúng Hoàng Trọng Nghĩa ơi,
Khi chọn một công cụ có sẵn được ví như ta chọn máy sinh tố để xay hoa quả: Không ai bảo chọn máy sinh tố là ngớ ngẩn cả, mà cái khái niệm nghĩ máy sinh tố không có phải cắt chém (lặp đi lặp lại việc cắt chém) thì là sai lầm ngớ ngẩn (ngớ ngẫn ở đây là đãng trí là lơ đãng là có thể chưa hiểu cơ bản, hay có thể dù không biết các công cụ có dùng vòng lặp hay không mà cứ khẳng định như đúng rùi là không có vòng lặp - vì đã đem ra đố thì tự mình phải có giải đáp, đáp án rui - không thể đánh lận còn đen muốn biết không hỏi mà lại ra vẻ đi đố được - chắc bạn không rơi vào trường hợp này)
Còn xưa nay ta vẫn có thể nói là nếu vấn đề nào sử dụng được các công cụ của sẵn trong excel, từ DLL tốt (như các DLL đã được Microsoft cung cấp) thì chắc chắn NHANH HƠN nhiều so với nếu chúng ta dùng cách thông thường viết (vì code VBA là code thuộc hạng chưa dịch - chạy ở tầng thứ cấp) - như việc không bao giờ người ta lại so sánh giữa cái có sẵn (máy xay sinh tố) đó với việc dùng từng bước (dùng dao tự cắt) rõ chưa - việc so sánh đó mới là ngớ ngẩn
Tuy thế, tùy từng quy mô công việc mà chúng ta sử dụng hay KHÔNG sử dụng công cụ có sẵn hay không? sao cho hợp lý ví như có mỗi một quả cherry nhỏ mà ném vào máy xay sinh tố thì thật là không đáng,
Túm lại, việc tôi nói "khái niệm về ngớ ngẩn" là ở chỗ đó chứ không phải giật mình đâu bạn ah,
Về việc đố vui ở đây, thì nhiều người nói rùi đó (cũng là lý do mà bài trên tôi chỉ trả lời và giải thích rõ bài #812 của bác siwtom):
...........
p/s : mà hình như chủ đề là " đố vui VBA " còn mấy cái vụ này không được gọi là "đố vui" roài , anh có thể rời bài ra topic " vui để đố " để không vi phạm nội quy
Bạn còn là MOD (mới nhìn lại màu mới thấy) nữa - càng phải cần tự xét lại mình xem bài viết cách hỏi, cách viết như thế đúng là hợp lý chưa nhé... xin cảm ơn
Ngớ ngẩn gì đâu chứ trong khi ta thấy nó KHÔNG VÒNG LẬP thì ta nói nó không lập thôi (bên trong ruốt nó lập hay không thây kệ nó)
Vấn đề là: Nếu ta tự viết được cái của riêng ta nó NHANH hơn thì ta xài, không thì cứ xài cái mà ta nghĩ là KHÔNG LẬP kia cho khỏe
Có gì đâu mà NGỚ với NGẨN nhỉ?
Cũng giống như dùng VBScript.RegEx, ta thấy nó không vòng lập và gọn thì ta xài ---> Ai rảnh đâu mà suy nghĩ bên trong ruột nó viết thế nào. Mà dù có cố suy nghĩ thì ta chắc gì đã biết bên trong nó có LẬP HAY KHÔNG LẬP mà bảo là NÓI SAI TỪ
----------------
Ngộ thiệt (tại ku Nghĩa bực mình thôi chứ em thì chẳng quan tâm)
Ẹc... Ẹc...
Em HIỂU hết những gì mọi người nói
Ẹc... Ẹc...
Có điều tại đồng chí kia nói hơi quá:
Ngớ ngẩn gì đâu chứ trong khi ta thấy nó KHÔNG VÒNG LẬP thì ta nói nó không lập thôi (bên trong ruốt nó lập hay không thây kệ nó)
Vấn đề là: Nếu ta tự viết được cái của riêng ta nó NHANH hơn thì ta xài, không thì cứ xài cái mà ta nghĩ là KHÔNG LẬP kia cho khỏe
Có gì đâu mà NGỚ với NGẨN nhỉ?
Cũng giống như dùng VBScript.RegEx, ta thấy nó không vòng lập và gọn thì ta xài ---> Ai rảnh đâu mà suy nghĩ bên trong ruột nó viết thế nào. Mà dù có cố suy nghĩ thì ta chắc gì đã biết bên trong nó có LẬP HAY KHÔNG LẬP mà bảo là NÓI SAI TỪ
----------------
Ngộ thiệt (tại ku Nghĩa bực mình thôi chứ em thì chẳng quan tâm)
Ẹc... Ẹc...
Khẳng định đó là sai từ, để lần sau chúng ta cùng không lặp lại ndu ah,
Vì nếu không lần sau lại đố tiếp lại nói KHÔNG DÙNG VÒNG LẶP thì làm nhiều người hiểu lầm sai bản chất vấn đề- và mất hết đi ý nghĩa thuật toán cơ bản (dù các công cụ kia vẫn sử dụng các thuật toán cơ bản mà thui - chúng ta cũng có thể từ thuật toán cơ bản mà xây dựng các công cụ tương tự chứ không phải cao siêu gì - đây cũng là cách hiểu sai về "đi tắt đón đầu" cuối cùng người ta lại vượt trước chúng ta vì họ đã có cái cơ bản nền tảng đê vượt và ta cứ trên mây trên ngọn)
Khẳng định đó là sai từ, để lần sau chúng ta cùng không lặp lại ndu ah,
Vì nếu không lần sau lại đố tiếp lại nói KHÔNG DÙNG VÒNG LẶP thì làm nhiều người hiểu lầm sai bản chất vấn đề- và mất hết đi ý nghĩa thuật toán cơ bản (dù các công cụ kia vẫn sử dụng các thuật toán cơ bản mà thui - chúng ta cũng có thể từ thuật toán cơ bản mà xây dựng các công cụ tương tự chứ không phải cao siêu gì - đây cũng là cách hiểu sai về "đi tắt đón đầu" cuối cùng người ta lại vượt trước chúng ta vì họ đã có cái cơ bản nền tảng đê vượt và ta cứ trên mây trên ngọn)
Hãy suy nghĩ đơn giản chút đi bạn, theo tui nghĩ thì việc viết không dùng vòng lặp có nghĩa là mình không được viết vòng lặp, nhưng không cấm việc sử dụng những công cụ mà bên trong nó có vòng lặp hay là không. Ta chả cần quan tâm bên trong nó có gì cho mệt xác, chỉ cần biết cái nào hợp, hay cảm thấy hay là dùng.
Khẳng định đó là sai từ, để lần sau chúng ta cùng không lặp lại ndu ah,
Vì nếu không lần sau lại đố tiếp lại nói KHÔNG DÙNG VÒNG LẶP thì làm nhiều người hiểu lầm sai bản chất vấn đề- và mất hết đi ý nghĩa thuật toán cơ bản (dù các công cụ kia vẫn sử dụng các thuật toán cơ bản mà thui - chúng ta cũng có thể từ thuật toán cơ bản mà xây dựng các công cụ tương tự chứ không phải cao siêu gì - đây cũng là cách hiểu sai về "đi tắt đón đầu" cuối cùng người ta lại vượt trước chúng ta vì họ đã có cái cơ bản nền tảng đê vượt và ta cứ trên mây trên ngọn)
Dạ vâng!
Bạn cho đó là SAI TỪ thì cứ thế đi (vì mình không biết thế nào là ĐÚNG cả, mình thấy nó không lập thì nói không lâp) Đứng trên cương vị là THÀNH VIÊN thì mình cũng chẳng quan tâm mấy vấn đề này (thích cái nào xài cái đó) Đứng trên cương vị là MOD thì mình thiết nghĩ cần phải nhắn nhủ đôi lời với bạn: Mai này dù có góp ý gì cũng cố lựa lời mà nói, tránh gây mất tình đoàn kết trên diễn đàn... Vì bạn và các thành viên khác trên diễn đàn này cũng chưa có mối quan hệ tốt đến mức có thể nói sao cũng được
Vậy đi nha!
Chúng ta tiếp tục ĐỐ VUI nhé
Đứng trên cương vị là THÀNH VIÊN thì mình cũng chẳng quan tâm mấy vấn đề này (thích cái nào xài cái đó) Đứng trên cương vị là MOD thì mình thiết nghĩ cần phải nhắn nhủ đôi lời với bạn: Mai này dù có góp ý gì cũng cố lựa lời mà nói, tránh gây mất tình đoàn kết trên diễn đàn... Vì bạn và các thành viên khác trên diễn đàn này cũng chưa có mối quan hệ tốt đến mức có thể nói sao cũng được
Chính vì dùng gì thì dùng --> thì mới cần đừng áp đặt quan niệm SAI của mình cho người khác,
Không phải không có lựa lời, mà đó là bài nói về khái niệm sai lầm (như là chắc chắn KHÔNG CÓ VÒNG LẶP trong các công cụ có sẵn) đó cần bỏ (nhấn mạnh để bỏ) --> không nói đến ai cả, thì sao là "mất tình đoàn kết" - trong chuyên môn cần thẳng thắn thừa nhận (khái niệm không đúng thì phải nói là không đúng), đừng tự ti như vậy
Cám ơn ndu đã nói vậy, và có thể hiểu là có quá nhiều nhạy cảm ở đây chăng (?)
Ở đây tôi thấy cách của huuthang_bd (selection sort) hay Quick sort của hungpecc1 (dĩ nhiên còn nhiều thuật toán sắp xếp khác - đó mới điều cần học cần nói mà không bị phủ nhận hoặc mờ đi bởi nhận định sai) là các cách cơ bản và ứng dụng tốt trong bài này - vì chẳng bao giờ có chuỗi nào tách mà dài lê văn thê đến hàng 10 000 thành phần tức là vài chục ngàn ký tự cả (nếu thế thì gọi là phi thực tế)
Chúc các bạn tiếp tục duy trì chủ đề đúng ý nghĩa đố vui của nó
Xét về tốc độ, thì 2 thằng em này cũng ngang ngang nhau, nếu dùng For ... Next do mình xử lý chuỗi thì có mà chờ dài cổ, tôi đã thử code của huuthang_bd với 1,000 mục cho ra thời gian đâu có bao nhiêu: 114 giây! Trong khi đó, với 60,000 mục thì 2 thằng em trên xử lý trong vòng 2 giây.
Các bạn dùng chuỗi nhưng các bạn lại lại "bắt" 3 < 20, tức coi 3 và 20 như số nên bắt buộc tôi phải sort mảng số. Vì tmp là mảng chuỗi nên tôi phải tạo mảng số Arr
Module1
Mã:
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long
Function SortArrayScript(SerStr As String) As String
SerStr = "('" & SerStr & "').split(',').sort(function(a,b){return (a-b)}).join(',')" ' & ".reverse()" 'if DESC
With CreateObject("MSScriptControl.ScriptControl")
.Language = "JavaScript"
SortArrayScript = .Eval(SerStr)
End With
End Function
Function SortArraySystem(SerStr As String) As String
Dim str As String, Arr, i As Long
Arr = Split(SerStr, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(Arr)
.Add CLng(Arr(i))
Next
.Sort: Arr = .ToArray
End With
SortArraySystem = Join(Arr, "-")
End Function
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laĚ maŇng câĚn săěp xęěp
' sortAtoZ xaěc điňnh caěch săěp xęěp tăng hay giaŇm
' iLo laĚ câňn dýőěi cuŇa maŇng Arr, iHi laĚ câňn tręn cuŇa maŇng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = Arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While Arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While Arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (Arr(Lo) > Arr(Hi))
Else
DoChange = (Arr(Lo) < Arr(Hi))
End If
If DoChange Then
s = Arr(Lo)
Arr(Lo) = Arr(Hi)
Arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort1DArray Arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Sub test()
Dim s As String, a As String, t As Double, k As Long, Arr() As Long, tmp, n As Long
t = GetTickCount
For k = 1 To 60000
a = SortArrayScript("1,9,1,2,1,8,16,4,3,11,11,9,5,11,12,13,16,15,20,15,14,10,7,20")
Next k
Debug.Print "SortArrayScript:: " & (GetTickCount - t) / 1000 & " " & a
t = GetTickCount
For k = 1 To 60000
a = SortArraySystem("1,9,1,2,1,8,16,4,3,11,11,9,5,11,12,13,16,15,20,15,14,10,7,20")
Next k
Debug.Print "SortArraySystem: " & (GetTickCount - t) / 1000 & " " & a
t = GetTickCount
For k = 1 To 60000
a = ""
tmp = Split("1,9,1,2,1,8,16,4,3,11,11,9,5,11,12,13,16,15,20,15,14,10,7,20", ",")
ReDim Arr(LBound(tmp) To UBound(tmp))
For n = LBound(tmp) To UBound(tmp)
Arr(n) = tmp(n)
Next n
QuickSort1DArray Arr, LBound(Arr), UBound(Arr), True
For n = LBound(tmp) To UBound(tmp)
a = a & Arr(n) & "-"
Next n
a = Left(a, Len(a) - 1)
Next k
Debug.Print "QuickSort1DArray: " & (GetTickCount - t) / 1000 & " " & a
End Sub
Hãy suy nghĩ đơn giản chút đi bạn, theo tui nghĩ thì việc viết không dùng vòng lặp có nghĩa là mình không được viết vòng lặp, nhưng không cấm việc sử dụng những công cụ mà bên trong nó có vòng lặp hay là không. Ta chả cần quan tâm bên trong nó có gì cho mệt xác, chỉ cần biết cái nào hợp, hay cảm thấy hay là dùng.
Hãy suy nghĩ đơn giản chút đi bạn, theo tui nghĩ thì việc viết không dùng vòng lặp có nghĩa là mình không được viết vòng lặp, nhưng không cấm việc sử dụng những công cụ mà bên trong nó có vòng lặp hay là không. Ta chả cần quan tâm bên trong nó có gì cho mệt xác, chỉ cần biết cái nào hợp, hay cảm thấy hay là dùng.
Chính suy nghĩ đơn giản đó mới dẫn đến hiểu nhầm, đến sai lầm bạn ah,
Phải chuẩn về mặt ngữ nghĩa khi nói về chuyên môn - nhất là lại đem đố (thành đề cho người khác) - tôi không nói bài riêng HTN đang đố mà nói chung về khái niệm sai lầm đó -- dẫn đến sự lầm tưởng cho người đọc, người áp dụng
Bạn hay ai thích đơn giản thì giữ riêng cho mình đừng viết ra khuyên người khác hay thách đố điều (đơn giản) sai đó được (dĩ nhiên có thể nói/ viết ra thì phải mở ngoặc giải thích rõ ràng - mà đã thế thì thà theo chuẩn chung phải hay hơn không). Vì đây là diễn đàn công khai cho cộng đồng, thì chúng ta phải chọn cái chuẩn chung cái đúng chung. Có như vậy mới giúp mọi người cùng tiến chứ không phải cứ hiểu ngầm định hay giả định quan niệm riêng của tôi.
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long
Function SortArraySystem(Arr)
Dim i As Long
With CreateObject("System.Collections.ArrayList")
For i = LBound(Arr) To UBound(Arr)
.Add Arr(i)
Next
.Sort
SortArraySystem = .ToArray
End With
End Function
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = Arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While Arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While Arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (Arr(Lo) > Arr(Hi))
Else
DoChange = (Arr(Lo) < Arr(Hi))
End If
If DoChange Then
s = Arr(Lo)
Arr(Lo) = Arr(Hi)
Arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort1DArray Arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Function Draw(Arr, Amount As Long)
Dim index As Long, k As Long, d As Long, c As Long, tmpArr, original
If Amount > UBound(Arr) - LBound(Arr) + 1 Then Exit Function
original = Arr
ReDim tmpArr(1 To Amount)
d = LBound(original)
c = UBound(original)
Randomize
For k = 1 To Amount
index = Int(Rnd() * (c - d + 1)) + d
tmpArr(k) = original(index)
original(index) = original(k + LBound(original) - 1)
d = d + 1
Next k
Draw = tmpArr
End Function
Sub test()
Dim t As Double, k As Long, Arr, tmp, identic As Boolean, he
ReDim Arr(1 To 500000)
ReDim he(1 To 500000)
For k = 1 To 500000
Arr(k) = k
Next k
Arr = Draw(Arr, 500000)
For k = 1 To 500000
he(k) = Arr(k)
Next k
' ------------------------------------------------------------------
t = GetTickCount
tmp = SortArraySystem(Arr)
Debug.Print "SortArraySystem: " & (GetTickCount - t) / 1000
t = GetTickCount
QuickSort1DArray he, LBound(he), UBound(he), True
Debug.Print "QuickSort1DArray: " & (GetTickCount - t) / 1000
' kiem tra xem 2 mang tmp va Arr co nhu nhau khong
identic = True
For k = 1 To 500000
If tmp(k - 1) <> he(k) Then
identic = False
Exit For
End If
Next k
Debug.Print "identic = " & identic
End Sub
kết quả em test là như sau :
[INFO1] SortArraySystem: 16.469 (1)
QuickSort1DArray: 7.453
identic = True[/INFO1]
Em nghĩ SortArraySystem sở dĩ lâu hơn vì nó phải mất công thực hiện 2 công việc :
*1 khai báo trễ createObject
* Tốn 1 vòng for để lại đưa từng phần tử mảng vào ArrayList ( .Add Arr(i))
--> em test lại như sau :
[GPECODE=vb]
Function SortArraySystem(Arr)
Dim i As Long
With CreateObject("System.Collections.ArrayList")
For i = LBound(Arr) To UBound(Arr)
.Add Arr(i)
Next
'.Sort
SortArraySystem = .ToArray
End With
End Function
[/GPECODE]
[GPECODE=vb]
Sub ktr()
Dim t As Double, k As Long, Arr
ReDim Arr(1 To 500000)
For k = 1 To 500000
Arr(k) = k
Next k
Arr = Draw(Arr, 500000)
t = GetTickCount
tmp = SortArraySystem(Arr)
Debug.Print "SortArraySystem: " & (GetTickCount - t) / 1000
End Sub
[/GPECODE]
kết quả là :SortArraySystem: 13.781 (2)
Tức là theo em phương thức .sort của System.Collections.ArrayList sẽ là =(1)-(2) =16.469-13.781=2.6(s) --> tốc độ quá khủng chăng
theo em hiểu thì cách sắp xếp của anh là phân đoạn
Mã:
iMid = Arr((Lo + Hi) \ 2)
-trường hợp xấu nhất là :iMid sẽ là giá trị lớn nhất , hoặc nhỏ nhất trong đoạn chia từ Lo đến Hi
- Nếu đẹp nhất là IMid bằng giá trị trung bình trong đoạn Lo Hi
---> em thử sửa iMid = INT[Rnd(Hi-Li+1)+Li] thì có lúc nhanh lúc chậm ,(có lúc chỉ còn 6,2 s < QuickSort1DArray =7.453)--> có cách nào chọn Imid tối ưu nhất không anh !
theo em hiểu thì cách sắp xếp của anh là phân đoạn
Mã:
iMid = Arr((Lo + Hi) \ 2)
-trường hợp xấu nhất là :iMid sẽ là giá trị lớn nhất , hoặc nhỏ nhất trong đoạn chia từ Lo đến Hi
- Nếu đẹp nhất là IMid bằng giá trị trung bình trong đoạn Lo Hi
---> em thử sửa iMid = INT[Rnd(Hi-Li+1)+Li] thì có lúc nhanh lúc chậm ,(có lúc chỉ còn 6,2 s < QuickSort1DArray =7.453)--> có cách nào chọn Imid tối ưu nhất không anh !
Sub test()
Dim t As Double, k As Long, Arr, tmp, identic As Boolean, he
ReDim Arr(1 To 500000)
ReDim he(1 To 500000)
For k = 1 To 500000
Arr(k) = 500001 - k
Next k
For k = 1 To 500000
he(k) = Arr(k)
Next k
' ------------------------------------------------------------------
t = GetTickCount
tmp = SortArraySystem(Arr)
Debug.Print "SortArraySystem: " & (GetTickCount - t) / 1000
t = GetTickCount
QuickSort1DArray he, LBound(he), UBound(he), True
Debug.Print "QuickSort1DArray: " & (GetTickCount - t) / 1000
' kiem tra xem 2 mang tmp va Arr co nhu nhau khong
identic = True
For k = 1 To 500000
If tmp(k - 1) <> he(k) Then
identic = False
Exit For
End If
Next k
Debug.Print "identic = " & identic
End Sub
Và nếu muốn thì cả sort tăng dần một mảng đã được sắp xếp tăng dần
Tức thay
Mã:
For k = 1 To 500000
Arr(k) = [B][COLOR=#ff0000]500001 -[/COLOR][/B] k
Next k
For k = 1 To 500000
he(k) = Arr(k)
Next k
bằng
Mã:
For k = 1 To 500000
Arr(k) = k
Next k
For k = 1 To 500000
he(k) = Arr(k)
Next k
Trên máy cũ kỹ của tôi kết quả hơi khác, thường là SortArraySystem/QuickSort1DArray ≈ 7
Quick sort nó là thế.
Nếu bạn định xét iMid với kiểu chọn tối ưu thì xin mời tự nghĩ ra thuật toán mới nhé.
Không có kiểu sort nào hoàn hảo 100%, trong mọi trường hợp cả. Bởi nếu thế thì có "ngần ấy" cách sort để mà làm gì? Chỉ có kiểu A tới ưu hơn B mà thôi.
À, bạn hãy chạy thử thêm code sau - sort tăng dần một mảng đã được sắp xếp giảm dần
Sub test()
Dim t As Double, k As Long, Arr, tmp, identic As Boolean, he
ReDim Arr(1 To 500000)
ReDim he(1 To 500000)
For k = 1 To 500000
Arr(k) = 500001 - k
Next k
For k = 1 To 500000
he(k) = Arr(k)
Next k
' ------------------------------------------------------------------
t = GetTickCount
tmp = SortArraySystem(Arr)
Debug.Print "SortArraySystem: " & (GetTickCount - t) / 1000
t = GetTickCount
QuickSort1DArray he, LBound(he), UBound(he), True
Debug.Print "QuickSort1DArray: " & (GetTickCount - t) / 1000
' kiem tra xem 2 mang tmp va Arr co nhu nhau khong
identic = True
For k = 1 To 500000
If tmp(k - 1) <> he(k) Then
identic = False
Exit For
End If
Next k
Debug.Print "identic = " & identic
End Sub
Và nếu muốn thì cả sort tăng dần một mảng đã được sắp xếp tăng dần
Tức thay
Mã:
For k = 1 To 500000
Arr(k) = [B][COLOR=#ff0000]500001 -[/COLOR][/B] k
Next k
For k = 1 To 500000
he(k) = Arr(k)
Next k
bằng
Mã:
For k = 1 To 500000
Arr(k) = k
Next k
For k = 1 To 500000
he(k) = Arr(k)
Next k
Mục đích của em là SORT, tìm những thủ tục, những hàm tối ưu, dự kiến sau này sẽ phát triển sắp xếp dữ liệu trên Excel 2007 trở về sau (hơn 1 triệu hàng), vì thế mới tung chiêu đố.
Tuy nhiên, em vẫn đánh giá cao SortArraySystem vì nó Sort vừa chuỗi vừa số được, chẳng hạn sắp xếp từ chuỗi này:
str = "a,9,8,c,6,7,b,3,a,f,4,6,7,e,10,1,11,33"
Kết quả = 1,10,11,3,33,4,6,6,7,7,8,9,a,a,b,c,e,f
Không biết hàm mình viết có được vậy không!? Hay có thể là hay hơn (sắp xếp chỗ tô đậm cho đúng vị trí)?
Function SortArraySystem(SerStr As String) As String
Dim str As String, Arr, i As Long
Arr = Split(SerStr, ",")
With CreateObject("System.Collections.ArrayList")
For i = 0 To UBound(Arr)
.Add CLng(Arr(i))
Next
.Sort: Arr = .ToArray
End With
SortArraySystem = Join(Arr, "-")
End Function
là sắp xếp mảng CHUỖI.
Do Arr được cắt từ chuỗi - Arr = Split(SerStr, ",") - nên nó là mảng chuỗi - mỗi phần tử là chuỗi. Tức vd. ta có "11" chứ không phải 11.
Nhưng trong code
Mã:
Function SortArraySystem(Arr)
Dim i As Long
With CreateObject("System.Collections.ArrayList")
For i = LBound(Arr) To UBound(Arr)
.Add Arr(i)
Next
.Sort
SortArraySystem = .ToArray
End With
End Function
Sub test()
Dim k As Long, Arr, tmp
ReDim Arr(1 To 500000)
For k = 1 To 500000
Arr(k) = k
Next k
Arr = Draw(Arr, 500000)
tmp = SortArraySystem(Arr)
End Sub
thì ta đã truyền vào hàm SortArraySystem một mảng số. Vì kiểu của mỗi phần tử là số (do Arr(k) = k mà k là Long)
Sub test()
Dim Arr, s As String
s = "a,9,8,c,6,7,b,3,a,f,4,6,7,e,10,1,11,33"
Arr = Split(s, ",")
QuickSort1DArray Arr, LBound(Arr), UBound(Arr), True
s = Join(Arr, ",")
Debug.Print s
End Sub
kết quả em test là như sau :
[INFO1] SortArraySystem: 16.469 (1)
QuickSort1DArray: 7.453
identic = True[/INFO1]
Em nghĩ SortArraySystem sở dĩ lâu hơn vì nó phải mất công thực hiện 2 công việc :
*1 khai báo trễ createObject
* Tốn 1 vòng for để lại đưa từng phần tử mảng vào ArrayList ( .Add Arr(i))
Tôi không nghĩ vậy!
Cái mình viết chỉ CHUYÊN DÙNG ĐỂ SORT (đâu có làm gì khác hơn)
Thằng System.Collections.ArrayList là 1 công cụ đồ sộ, nó đâu chỉ có SORT
Vậy nên nếu phần sort cho tốc độ thấp hơn cũng là chuyện quá bình thường
Từ xưa tôi vẫn biết cái QuickSort của anh siwtom nó nhanh nhưng phải nói thằng thế này:
- Rất nhiều người lúng túng khi dùng QụickSort của anh siwtom (em nói thật, mong anh đừng buồn). Có thể vì cách viết của anh chưa "gần gũi" chẳng?
- Với System.Collections.ArrayList: Đơn giản + tốc độ chấp nhận được + Nhìn là hiểu + áp dụng được ngay
Tôi không nghĩ vậy!
Cái mình viết chỉ CHUYÊN DÙNG ĐỂ SORT (đâu có làm gì khác hơn)
Thằng System.Collections.ArrayList là 1 công cụ đồ sộ, nó đâu chỉ có SORT
Vậy nên nếu phần sort cho tốc độ thấp hơn cũng là chuyện quá bình thường
Từ xưa tôi vẫn biết cái QuickSort của anh siwtom nó nhanh nhưng phải nói thằng thế này:
- Rất nhiều người lúng túng khi dùng QụickSort của anh siwtom (em nói thật, mong anh đừng buồn). Có thể vì cách viết của anh chưa "gần gũi" chẳng?
- Với System.Collections.ArrayList: Đơn giản + tốc độ chấp nhận được + Nhìn là hiểu + áp dụng được ngay
Em thì hiểu như vậy , không biết có đúng không :
iLo = integer Low, iHi = integer Hight --> tức là chỉ số trên và dưới của một đoạn phần tử trong mảng : Arr(iLo) : Arr(iHi)
* Vì đây là cách viết theo thuật toán đệ quy --> bắt buộc phải có 2 đối số iLo và iHi trong QuickSort
Em thì hiểu như vậy , không biết có đúng không :
iLo = integer Low, iHi = integer Hight --> tức là chỉ số trên và dưới của một đoạn phần tử trong mảng : Arr(iLo) : Arr(iHi)
* Vì đây là cách viết theo thuật toán đệ quy --> bắt buộc phải có 2 đối số iLo và iHi trong QuickSort
Em thì hiểu như vậy , không biết có đúng không :
iLo = integer Low, iHi = integer Hight --> tức là chỉ số trên và dưới của một đoạn phần tử trong mảng : Arr(iLo) : Arr(iHi)
* Vì đây là cách viết theo thuật toán đệ quy --> bắt buộc phải có 2 đối số iLo và iHi trong QuickSort
Có thể về nguyên tắc của thuật toán nào đó thì phải bắt buộc như thế, nhưng với VBA của Excel thì không cần, vậy thì ta cứ giản thiểu biến một cách không cần thiết là được chứ nhỉ?
Có thể về nguyên tắc của thuật toán nào đó thì phải bắt buộc như thế, nhưng với VBA của Excel thì không cần, vậy thì ta cứ giản thiểu biến một cách không cần thiết là được chứ nhỉ?
Em không hiểu ý anh lắm, em lấy 1 ví dụ ngắn gọn thế này !
[GPECODE=vb]
Sub quicksort(subArr(), ByVal L As Long, ByVal U As Long)
Dim i As Long, j As Long
Dim pivot, TG
If L >= U Then Exit Sub <--- Đây là điểm neo, nếu không có điểm này sẽ là vòng lặp vô tận
i = L: j = U
pivot = Int(Rnd() * (j - i + 1) + i)
Do
While subArr(i) < subArr(pivot)
i = i + 1
Wend
While subArr(j) > subArr(pivot)
j = j - 1
Wend
If i <= j Then
TG = subArr(i): subArr(i) = subArr(j): subArr(j) = TG
i = i + 1
j = j - 1
End If
Loop Until i > j
quicksort subArr, L, j <---------- Đệ quy với tham số L,J
quicksort subArr, i, U<---------- Đệ quy với tham số i,U
End Sub
Nếu mà không có 2 tham số L,U thì anh phải tạo thêm 1 điểm neo nữa
[/GPECODE]
Tài liệu tham khảo trên google : 1. Sơ lược
Giải thuật Quick Sort là một phương pháp sắp xếp theo kiểu phân đoạn được cải tiến từ thuật toán Selection Sort do C.A.R Hoare đưa ra. Cụ thể như sau:
Đầu tiên cần chọn một phần tử nào đó của dãy làm chốt hay phần tử quay (pivot).
Trong bước tiếp theo, các phần tử nhỏ hơn chốt phải được xếp vào phía trước chốt (đầu dãy) và các
phần tử lớn hơn được xếp vào phía sau chốt (cuối dãy). Để có được sự phân loại này, các phần tử sẽ được so
sánh với chốt và hoán đổi vị trí cho nhau hoặc cho chốt nếu nó lớn hơn chốt mà lại nằm trước
hoặc nhỏ hơn chốt mà lại nằm sau. Khi lượt hoán đổi đầu tiên thực hiện xong thì dãy được chia
thành 2 đoạn: 1 đoạn bao gồm các phần tử nhỏ hơn chốt, đoạn còn lại bao gồm các phần tử lớn
hơn chốt, còn chốt chính là phần tử đã được sắp xếp.
Áp dụng kĩ thuật trên cho từng phân đoạn cho tới khi mỗi đoạn chỉ còn lại 2 phần tử thì việc sắp xếp kết thúc.
2. Ví dụ
Sắp xếp dãy sau bằng giải thuật Quick Sort:
Chỉ số : 0 1 2 3 4 5 6 7 8 9
Mảng A : 37 11 25 44 55 28 98 84 54 73
Ta chọn chốt đầu tiên là 37. Để tìm 2 khóa cần đổi chỗ cho nhau, ta dùng 2 biến i và j với giá trị ban đầu: i=1, j=9.
Nếu Ai<37 thì tiếp tục tăng i lên 1 và lặp lại, cho tới khi gặp phần tử Ai>37.
Duyệt các phần tử Aj, nếu Aj>37 thì giảm j đi một, cho tới khi gặp phần tử Aj<37.
Nếu i còn nhỏ hơn j thì đổi chỗ Ai và Aj tìm được cho nhau.
Quá trình lặp lại với Ai và Aj cho đến khi i=j, chính là vị trí dành cho khóa 37.
Cuối cùng ta đổi chỗ 37 cho khóa Aj.
Lượt đầu tiên i dừng lại ở A3=44, j dừng lại ở A5=28.
37 11 25 44 55 28 98 84 54 73
Chốt -----I -----j
Đổi chỗ 44 và 28:
37 11 25 28 55 44 98 84 54 73
------------I ---j
Tiếp tục chạy Ai từ 28 và Aj từ 44, i dừng lại ở A4=55, j dừng lại ở A3=28:
37 11 25 28 55 44 98 84 54 73
----------J-- i
Lúc này i>j, ta đổi chỗ chốt 37 cho Aj=28 được:
28 11 25 37 55 44 98 84 54 73
Như vậy kết thúc lần thứ nhất ta được hai đoạn được phân biệt bởi khóa 37 như sau:
28 11 25 [37] 55 44 98 84 54 73
Quá trình được lặp lại tương tự cho từng phân đoạn trên cho tới khi dãy được sắp xếp hoàn toàn
Em không hiểu ý anh lắm, em lấy 1 ví dụ ngắn gọn thế này !
[GPECODE=vb]
Sub quicksort(subArr(), ByVal L As Long, ByVal U As Long)
Dim i As Long, j As Long
Dim pivot, TG
If L >= U Then Exit Sub <--- Đây là điểm neo, nếu không có điểm này sẽ là vòng lặp vô tận
i = L: j = U
pivot = Int(Rnd() * (j - i + 1) + i)
Do
While subArr(i) < subArr(pivot)
i = i + 1
Wend
While subArr(j) > subArr(pivot)
j = j - 1
Wend
If i <= j Then
TG = subArr(i): subArr(i) = subArr(j): subArr(j) = TG
i = i + 1
j = j - 1
End If
Loop Until i > j
quicksort subArr, L, j <---------- Đệ quy với tham số L,J
quicksort subArr, i, U<---------- Đệ quy với tham số L,J
End Sub
Nếu mà không có 2 tham số L,U thì anh phải tạo thêm 1 điểm neo nữa
[/GPECODE]
Vậy thôi ta tìm cách "quăng" biến ấy ra ngoài ở dạng Public hay gì đó đi
Nói chung là tôi không có khả năng sửa code, chỉ đứng trên QUAN ĐIỂM NGƯỜI DÙNG mà ĐÒI HỎI thôi
Ẹc... Ẹc...
Em thì hiểu như vậy , không biết có đúng không :
iLo = integer Low, iHi = integer Hight --> tức là chỉ số trên và dưới của một đoạn phần tử trong mảng : Arr(iLo) : Arr(iHi)
* Vì đây là cách viết theo thuật toán đệ quy --> bắt buộc phải có 2 đối số iLo và iHi trong QuickSort
Vậy thôi ta tìm cách "quăng" biến ấy ra ngoài ở dạng Public hay gì đó đi
Nói chung là tôi không có khả năng sửa code, chỉ đứng trên QUAN ĐIỂM NGƯỜI DÙNG mà ĐÒI HỎI thôi
Ẹc... Ẹc...
Có thể về nguyên tắc của thuật toán nào đó thì phải bắt buộc như thế, nhưng với VBA của Excel thì không cần, vậy thì ta cứ giản thiểu biến một cách không cần thiết là được chứ nhỉ?
Tôi viết code 10 tháng trước. Có lúc nào tôi phàn nàn rằng không ai quan tâm, không ai dùng đâu. Tôi là ai mà có quyền ép mọi người dùng code của mình? Tôi không phàn nàn gì cả. Chỉ tới khi bạn so code của mình với code của huuthang_bd để rồi từ trên đỉnh cao chiến thắng diễu cợt vodoi2x
Thế cho nên đừng ai vỗ ngực xưng tên tôi hay và chê người ta ngớ ngẫn, mà hãy học thêm và biết chọn lọc tinh hoa của người khác mà ứng dụng vô công việc của mình. Bạn có giỏi thì cứ cắt bằng tay đi rồi nghiền nát, còn tôi thì dùng máy xay sinh tố vậy!
Bạn nghĩ là nó thừa hay bạn chắc chắn là nó thừa? Nếu chắc chắn thì vứt nó đi. Nếu sau đó code không chạy thì tự sửa.
Sức tôi có hạn thôi bạn ạ. Đâu có được như những vĩ nhân, siêu nhân, sư phụ GPE.
Tôi viết code 10 tháng trước. Có lúc nào tôi phàn nàn rằng không ai quan tâm, không ai dùng đâu. Tôi là ai mà có quyền ép mọi người dùng code của mình? Tôi không phàn nàn gì cả. Chỉ tới khi bạn so code của mình với code của huuthang_bd để rồi từ trên đỉnh cao chiến thắng diễu cợt vodoi2x
tôi mới đưa nó ra cho bạn xem. Thế thôi.
Tôi cũng đã trả lời câu mỉa mai "nó nằm tuốt luốt dưới đáy đại dương" ở chủ đề bên kia
Trước tiên, em xin nói rõ là em chẳng mỉa mai ai cả, chẳng qua là dùng từ cường điệu thôi, không có gì gọi là mỉa mai nhất là đối với bậc Thầy, bậc tiền bối cả.
Kế tiếp em nói thừa là vì sao, thay vì code thế này:
Mã:
Public Sub QuickSort1DArray(arr, [COLOR=#ff0000][B]iLo As Long, iHi As Long[/B][/COLOR], ByVal sortAtoZ As Boolean)
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (arr(Lo) > arr(Hi))
Else
DoChange = (arr(Lo) < arr(Hi))
End If
If DoChange Then
s = arr(Lo)
arr(Lo) = arr(Hi)
arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort1DArray arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Thì người viết code có thể thay đổi chút đỉnh cho người dùng cảm thấy tiện lợi hơn như thế này:
Mã:
Public Sub QuickSort1DArray(arr, ByVal sortAtoZ As Boolean)
[COLOR=#000000]
[/COLOR][COLOR=#ff0000][B]Dim iLo As Long, iHi As Long
iLo = LBound(Arr): iHi = UBound(Arr)[/B][/COLOR]
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (arr(Lo) > arr(Hi))
Else
DoChange = (arr(Lo) < arr(Hi))
End If
If DoChange Then
s = arr(Lo)
arr(Lo) = arr(Hi)
arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort1DArray arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Và cấu trúc đó, người dùng chỉ cần biết mảng đầu vào và chiều sort thôi:
QuickSort1DArray UserArr, True/False
Phải chăng là tiên lợi hơn chăng? Có ảnh hưởng gì đến code không?
Thầy góp ý cho em thì em rất vui lòng đón nhận vì kiến thức của Thầy rất vĩ đại, chẳng lẽ một góp ý cỏn con vậy mà Thầy lại khó chịu đến thế hay sao?
Bạn không phải đoán mò gì cả. Tôi là người có trách nhiệm nên thường giải thích rất kỹ. Cả ý nghĩa của đối số và chú thích cả những chỗ quan trọng trong code. Nếu bạn đọc code thì bạn sẽ thấy ngay trên đầu
Mã:
' Arr là mảng cần sắp xếp
' sortAtoZ xác định cách sắp xếp tăng hay giảm
' iLo là cận dưới của mảng Arr, iHi là cận trên của mảng Arr
Chuyện tác giả viết code như thế nào là chuyện của người ta. Nếu mình thấy dùng được thì dùng còn nếu thấy không hợp lý thì tự viết. Thế thôi. Ai đời lại có chuyện phỉ báng tác giả. Có thể người ta viết thế vì sức của người ta có thế, viết được như thế là cạn kiến thức rồi. Mình không vừa lòng thì vứt đi rồi tự viết. Mà có phỉ báng người ta thì trước tiên hãy tự viết, nếu được hãy phỉ báng.
Hix tại code bài #833 có đoạn này em không dịch được nên mới hỏi là " không biết có đúng không ?" chứ em có "đoán mò " theo ý hiểu của anh đâu :?
Mã:
Trích từ code bài #833
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laE maNng câEn saep xeep
' sortAtoZ xaec dinnh caech saep xeep tang hay giaNm
' iLo laE cânn dýoei cuNa maNng Arr, iHi laE cânn tren cuNa maNng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Trước tiên, em xin nói rõ là em chẳng mỉa mai ai cả, chẳng qua là dùng từ cường điệu thôi, không có gì gọi là mỉa mai nhất là đối với bậc Thầy, bậc tiền bối cả.
Kế tiếp em nói thừa là vì sao, thay vì code thế này:
Thì người viết code có thể thay đổi chút đỉnh cho người dùng cảm thấy tiện lợi hơn như thế này:
Mã:
Public Sub QuickSort1DArray(arr, ByVal sortAtoZ As Boolean)
[COLOR=#000000]
[/COLOR][COLOR=#ff0000][B]Dim iLo As Long, iHi As Long
iLo = LBound(Arr): iHi = UBound(Arr)[/B][/COLOR]
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (arr(Lo) > arr(Hi))
Else
DoChange = (arr(Lo) < arr(Hi))
End If
If DoChange Then
s = arr(Lo)
arr(Lo) = arr(Hi)
arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then [COLOR=#ff0000]QuickSort1DArray arr , sortAtoZ[/COLOR]
iLo = Lo
Loop Until Lo >= iHi
End Sub
Và cấu trúc đó, người dùng chỉ cần biết mảng đầu vào và chiều sort thôi:
QuickSort1DArray UserArr, True/False
Phải chăng là tiên lợi hơn chăng? Có ảnh hưởng gì đến code không?
Thầy góp ý cho em thì em rất vui lòng đón nhận vì kiến thức của Thầy rất vĩ đại, chẳng lẽ một góp ý cỏn con vậy mà Thầy lại khó chịu đến thế hay sao?
Hix tại code bài #833 có đoạn này em không dịch được nên mới hỏi là " không biết có đúng không ?" chứ em có "đoán mò " theo ý hiểu của anh đâu :?
Mã:
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laE maNng câEn saep xeep
' sortAtoZ xaec dinnh caech saep xeep tang hay giaNm
' iLo laE cânn dýoei cuNa maNng Arr, iHi laE cânn tren cuNa maNng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Ơ lạ nhỉ?
Tôi có sửa gì đâu? Tự bạn đề nghị và tự bạn sửa. Tôi chỉ nói là: để biết code sau khi sửa có chạy không thì không cần phải hỏi ai cả. Thế thôi.
Hix cái vụ này là ý em muốn nhắn tới anh nghĩa với nội dung sau :
Nếu anh định viết theo kiểu dim iLo..... thì anh nên test trước khi post bài ,xem code có hoạt động không thôi !
Hix cái vụ này là ý em muốn nhắn tới anh nghĩa với nội dung sau :
Nếu anh định viết theo kiểu dim iLo..... thì anh nên test trước khi post bài ,xem code có hoạt động không thôi !
OK, có lẽ lần đầu tiên tôi thấy Sub chạy trong chính Sub đó nên tôi thắc mắc như thế, nếu đã đóng gói như là thư viện và chẳng thấy được mã nguồn thì thôi, còn đằng này thấy được mã nguồn và thắc mắc thì cũng là chuyện rất bình thường, nhưng qua đó sẽ được biết thêm về thủ tục này.
Như thế, tôi tự nhận khuyết điểm là "Có mắt mà không nhìn thấy Thái Sơn".
QuickSort là một trong những bài toán căn bản của lập trình.
Người nào học về thuật toán lập trình đều có học qua nó. Và bao nhiêu năm nay nó vẫn được viết với tham số như vậy, chả giảm thiểu được gì cả.
Lý do không thể dùng biến public/global (biến toàn cục):
- Về cách áp dụng: đây là hàm căn bản để dùng làm hàm thư viện. Theo nguyên tắc, hàm thư viện không được dùng biến toàn cục.
- Về cơ cấu code: đây là bài toán đệ quy, mà lại là đệ quy phi tuyến - tức là chính nó chẻ ra để gọi lại nó nhiều lần. Dùng biến toàn cục rất rắc rối và dễ sai.
Theo lệ thường, người ta chỉ dùng biến toàn cục khi sợ bị hết bộ nhớ cho ngăn xếp (stack). Nhưng đã sợ không đủ bộ nhớ thì đừng dùng hàm đệ quy nagy từ đầu.
- Về cơ cấu code: đây là bài toán đệ quy, mà lại là đệ quy phi tuyến - tức là chính nó chẻ ra để gọi lại nó nhiều lần. Dùng biến toàn cục rất rắc rối và dễ sai.
Private Sub QuickSort(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laĚ maŇng câĚn săěp xęěp
' sortAtoZ xaěc điňnh caěch săěp xęěp tăng hay giaŇm
' iLo laĚ câňn dýőěi cuŇa maŇng Arr, iHi laĚ câňn tręn cuŇa maŇng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = Arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While Arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While Arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (Arr(Lo) > Arr(Hi))
Else
DoChange = (Arr(Lo) < Arr(Hi))
End If
If DoChange Then
s = Arr(Lo)
Arr(Lo) = Arr(Hi)
Arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort Arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Public Sub QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean)
QuickSort Arr, LBound(Arr), UBound(Arr), sortAtoZ
End Sub
Tôi thấy là chả có lý do chính đáng nào để mà phải làm cho code nó phức tạp lên nên viết như vậy.
Nếu chuyện gõ thêm 2 thông số là việc làm hàng ngày, và mỗi ngày gõ 1000 lần thì tôi còn hiểu được đó là cực hình. Còn không thì không lý gì lại làm phức tạp code để chiều các vị lười. Vì chuyện gõ 2 thông số không phải là cực hình, cũng không là việc gây lúng túng cho người dùng. Gõ gõ thì có gì mà lúng túng.
Còn cứ muốn gõ ít thôi, và chỉ yêu sách duy nhất về chuyện gõ thêm thôi thì có khó gì?
code cho những người ngại gõ
Mã:
Public Sub QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean)
QuickSort Arr, LBound(Arr), UBound(Arr), sortAtoZ
End Sub
Gõ thì không ngại gì đâu Thầy ơi, nhưng với cách này (thêm 1 thủ tục như Thầy vừa làm) thì người dùng họ sẽ thấy "gần gũi" hơn. Giả sử em không biết gì về Ubound, về Lbound hay đại loại là không biết gì về mảng, em chỉ biết chép vào module và chạy code, thấy sướng quá, đem áp dụng luôn, vậy thì kiểu này QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean) người dùng sẽ sướng hơn đấy.
Vì kiến thức em chỉ học lõm tại diễn đàn này, không biết "quái" gì về "bài toán đệ quy hay đệ quy phi tuyến" vì thế làm sao mà biết được cách thức mà biến nó hoạt động như thế nào!
Và vì chả biết gì nên phát biểu linh tinh như thế đấy thôi (điếc không sợ súng là vậy đó Thầy ơi), thông cảm cho em.
Gõ thì không ngại gì đâu Thầy ơi, nhưng với cách này (thêm 1 thủ tục như Thầy vừa làm) thì người dùng họ sẽ thấy "gần gũi" hơn. Giả sử em không biết gì về Ubound, về Lbound hay đại loại là không biết gì về mảng, em chỉ biết chép vào module và chạy code, thấy sướng quá, đem áp dụng luôn, vậy thì kiểu này QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean) người dùng sẽ sướng hơn đấy.
Vì kiến thức em chỉ học lõm tại diễn đàn này, không biết "quái" gì về "bài toán đệ quy hay đệ quy phi tuyến" vì thế làm sao mà biết được cách thức mà biến nó hoạt động như thế nào!
Và vì chả biết gì nên phát biểu linh tinh như thế đấy thôi (điếc không sợ súng là vậy đó Thầy ơi), thông cảm cho em.
...
Vì kiến thức em chỉ học lõm tại diễn đàn này, không biết "quái" gì về "bài toán đệ quy hay đệ quy phi tuyến" vì thế làm sao mà biết được cách thức mà biến nó hoạt động như thế nào!
...
Đệ quy trực tuyến là gọi lại theo đường thẳng, hàm gọi lại chính nó thẳng tuột một cách trực tiếp - ví dụ hàm tính giai thừa là tiêu biểu; dựa trên công thức n! = n*(n-1)!
Đệ quy phi tuyến không gọi trực tiếp theo đường thẳng mà có thể:
- Tán tuyến: chia ra nhiều nhánh, và lộn lại theo từng nhánh - tiêu biểu là bài quicksort
- Cách tuyến: rất rắc rối, hàm A gọi B, B gọi ngược lại A...
- Hỗn hợp đủ các kiểu trên.
Anh siwtom à!
Anh và em quen nhau trên diễn đàn này, thời gian tuy không dài nhưng cũng đủ để anh hiểu được con người em không phải thuộc loại thích bắt bẻ từng câu chữ.
Em tôn trọng anh vì kiến thức của anh... Em HỎI nhằm mục đích để HỌC. Em thấy "lúng túng" thì nói là "lúng túng"
Không ngờ chỉ câu hỏi nhỏ của em lại khiến anh mất bình tỉnh đến vậy
Thôi thì em xin lỗi... Hứa rằng sẽ không hỏi thêm gì nữa
Vậy đi nha!
Anh siwtom à!
Anh và em quen nhau trên diễn đàn này, thời gian tuy không dài nhưng cũng đủ để anh hiểu được con người em không phải thuộc loại thích bắt bẻ từng câu chữ.
Em tôn trọng anh vì kiến thức của anh... Em HỎI nhằm mục đích để HỌC. Em thấy "lúng túng" thì nói là "lúng túng"
Không ngờ chỉ câu hỏi nhỏ của em lại khiến anh mất bình tỉnh đến vậy
Thôi thì em xin lỗi... Hứa rằng sẽ không hỏi thêm gì nữa
-
Ngoài lề: Có dịp phải phạt ku Nghĩa! Vì cứ bài nào chú mày "khơi mào" là y như rằng có tranh chấp (có hiện tượng nóng lên toàn cầu)...
Chú phải "kiểm điểm" bản thân đi nha (bằng 1 chầu gì đó cũng được)
-
Ngoài lề: Có dịp phải phạt ku Nghĩa! Vì cứ bài nào chú mày "khơi mào" là y như rằng có tranh chấp (có hiện tượng nóng lên toàn cầu)...
Chú phải "kiểm điểm" bản thân đi nha (bằng 1 chầu gì đó cũng được)
Đồng ý với Thầy ndu
Chú Nghĩa chở bạn gái rủ mình & ku Tùng, ku Leo......... đi Biên Hòa kêu ku Thương ra............phạt một bữa
Từ hôm sinh nhật đến nay chưa "óp- iếc" gì cả, nhớ nhớ. À mà ku Nhím về Sì- Gòn chưa nhỉ, chẳng thấy tăm hơi đau cả ??????????
"Chết mẹ", cái này xì- pam rồi
Như vậy là THÊM VIỆC không cần thiết cho hàm
Nghĩa cứ nghĩ xem: Ngay cả công cụ sort của Excel khi làm việc cũng phân biệt rõ ràng chuổi và số mà
Vậy, muốn nó sort đúng "ý mình" thì cứ chuyển các phần tử của Arr2 thành số trước đi ---> Có tốn công sức gì đâu ---> Vì nếu "chiều ý" của Nghĩa thì hàm sẽ không mang tính tổng quát (mình chú xài)
Như vậy là THÊM VIỆC không cần thiết cho hàm
Nghĩa cứ nghĩ xem: Ngay cả công cụ sort của Excel khi làm việc cũng phân biệt rõ ràng chuổi và số mà
Vậy, muốn nó sort đúng "ý mình" thì cứ chuyển các phần tử của Arr2 thành số trước đi ---> Có tốn công sức gì đâu ---> Vì nếu "chiều ý" của Nghĩa thì hàm sẽ không mang tính tổng quát (mình chú xài)
Tổng quát chứ Thầy, bởi trong một mảng vừa chuỗi vừa số, ta sắp xếp chúng có trật tự hơn vì chúng tự biết đâu là chuỗi, đâu là số dạng chuỗi. Còn việc em đưa ra cái mảng đó mà xử lý thì em đưa trường hợp đó lên đây làm gì nữa Thầy ơi, bởi ngay cái tên Sub đã nói rằng Sort mảng 1 chiều, vậy cái mảng Arr2 chẳng phải là mảng 1 chiều sao? Hay là ta phải ghi chú rằng Sub này sẽ không Sort được chính xác mảng từ hàm Split xuất ra?
Tổng quát chứ Thầy, bởi trong một mảng vừa chuỗi vừa số, ta sắp xếp chúng có trật tự hơn vì chúng tự biết đâu là chuỗi, đâu là số dạng chuỗi. Còn việc em đưa ra cái mảng đó mà xử lý thì em đưa trường hợp đó lên đây làm gì nữa Thầy ơi, bởi ngay cái tên Sub đã nói rằng Sort mảng 1 chiều, vậy cái mảng Arr2 chẳng phải là mảng 1 chiều sao? Hay là ta phải ghi chú rằng Sub này sẽ không Sort được chính xác mảng từ hàm Split xuất ra?
Tổng quát chứ Thầy, bởi trong một mảng vừa chuỗi vừa số, ta sắp xếp chúng có trật tự hơn vì chúng tự biết đâu là chuỗi, đâu là số dạng chuỗi. Còn việc em đưa ra cái mảng đó mà xử lý thì em đưa trường hợp đó lên đây làm gì nữa Thầy ơi, bởi ngay cái tên Sub đã nói rằng Sort mảng 1 chiều, vậy cái mảng Arr2 chẳng phải là mảng 1 chiều sao? Hay là ta phải ghi chú rằng Sub này sẽ không Sort được chính xác mảng từ hàm Split xuất ra?
1. Bạn nói đúng. Sub này sẽ không Sort được chính xác mảng từ hàm Split xuất ratheo như ý muốn của bạn. Tôi thú nhận như thế bạn đã hài lòng chưa? Bạn có thể quên nó đi được rồi. Bạn có bao nhiêu lựa chọn cơ mà?
2. Sub của tôi sort theo kiểu số nếu mảng vào là mảng toàn số, còn nếu là mảng toàn chuỗi thì sort theo kiểu chuỗi.
Sub của tôi không kiểm tra xem liệu dữ liệu có đổi thành số được không. Cũng không có ý định đổi bất cứ cái gì thành số, thậm chí khi có thể. Có 3 lý do:
a. Tôi cho rằng việc tạo một mảng đúng ý để truyền vào sub là không khó, không mất nhiều thời gian. Chả lý gì sub lại đi làm cái việc không đâu.
b. Tôi là tác giả, dụng ý của tôi là thế. Nếu bạn thấy hay thì dùng, không hay thì bỏ qua. Không ai dí súng vào đầu bạn bắt bạn phải dùng cả.