2010-10-06 38 views
5

Tôi cần biết liệu tất cả các ký tự trong một chuỗi có bằng nhau hay không (được tạo thành bởi cùng một ký tự). hàm phải trả về true hoặc false phụ thuộc vào tất cả các phần tử của chuỗi bằng với một char cụ thể.Cách xác định xem tất cả các ký tự trong một chuỗi có bằng nhau không

Tôi đã viết hàm này hoạt động tốt, nhưng tôi đang tìm giải pháp tối ưu (nhanh nhất), các chuỗi có thể có hàng nghìn ký tự.

function AllElementsAreEqual(Element:Char;Str:String):Boolean; 
var 
    i : Integer; 
begin 
Result:=True; 
if Str<>'' then 
    for i:=1 to Length(Str) do 
    if Str[i]<>Element then 
    begin 
     Result:= False; 
     exit; 
    end; 
end; 

CẬP NHẬT cuối cùng bằng cách sử dụng Barry Kelly Đề xuất và bổ sung các chỉ thị inline, hiệu suất được cải thiện đáng kể.

function AllElementsAreEqual(Const Element:Char;Str:String):Boolean;inline; 
type 
ArrayInt = Array of Integer; 
var 
    i : Integer; 
    Delta: Integer; 
    List : ArrayInt; 
    Test : Integer; 
begin 
    Result:=True; 
    Delta:=(Length(Str) mod 4); 
    if Delta<>0 then 
    Str:=Str+StringOfChar(Element,4-Delta); 
    Test:=Ord(Element) + Ord(Element) shl 8 + Ord(Element) shl 16 + Ord(Element) shl 24; 
    List:=ArrayInt(@(Str[1])); 

    for i:=0 to ((Length(Str) div 4)-1) do 
    if List[i]<>Test then 
    begin 
    Result:=False; 
    exit; 
    end; 
end; 

UPDATE 2

Tôi xin lỗi nhưng tôi đã đăng một thi cũ của các giải pháp (với một lỗi), bây giờ là cố định. Nhờ có The_Fox để tạo một triển khai tốt hơn đề xuất Barry.

+0

lý do tại sao không sử dụng "===" ba bằng thats những gì được sử dụng. so sánh nếu điều đó là hoàn toàn =. Kiểm tra kiểu dữ liệu cũng như các ký tự – Val

+3

@Val, vì khi nào Delphi có "==="? Bạn đang bối rối với Delphi với JavaScript? –

+0

xấu của tôi Tôi đã suy nghĩ về một cái gì đó khác ... – Val

Trả lời

9

Bạn có thể xem xét việc tạo ra một giá trị Integer với Element lặp đi lặp lại 4 lần (vì đây là AnsiChar trong Delphi 7), chuyển như Ord(Element) + Ord(Element) shl 8 + Ord(Element) shl 16 + Ord(Element) shl 24, sau đó định kiểu chuỗi thành một PIntegerArray (^array[0..MaxInt div 4 - 1] of Integer) và vòng qua nó Length(Str) div 4 lần, so sánh như số nguyên thay vì ký tự. Bạn sẽ cần phải so sánh một số ít nhất Length(str) mod 4 ký tự theo cách thủ công.

+0

Đây có phải là loại lừa trình biên dịch Delphi sử dụng để được nhanh như vậy?;) –

+0

Nó là một của các thủ thuật nó sử dụng cho băm chuỗi và so sánh, có. –

0

Có thể sử dụng StringOfChar để tạo chuỗi có mục tiêu char lặp lại N lần, sau đó thực hiện so sánh chuỗi thay vì so sánh char-by-char.

(Không biết nếu điều này thực sự nhanh hơn; đo lường & xem).

-3

Từ những gì tôi hiểu từ mã của bạn

Result:= False; 

": =" được dùng để gán giá trị cho một biến. làm thế nào để bạn so sánh 2 giá trị trong delphi?

+0

Các nhà khai thác ở Delphi: http://library.thinkquest.org/C006657/delphi/operators_in_delphi.htm –

+1

Một cách hợp lý, với dấu bằng, thay vì bằng bằng hoặc === hoặc kỳ quặc khác. : = thường được đọc là "được gán cho" hoặc "trở thành". == đến từ "C" (và ban đầu "B"). Tuy nhiên BCPL được sử dụng: =, đến từ Algol. Bởi vì quyết định kỳ quặc này (có lẽ bởi Thompson và/hoặc Ritchie) hàng ngàn lỗi đã được tạo ra bằng cách lạm dụng = chứ không phải == –

+0

thiên tài, làm thế nào tôi có thể không bao giờ nghĩ về điều đó. Thành thật mà nói, tôi đã không bao giờ được nhìn thấy một câu trả lời tuyệt vời như vậy, nhưng bạn đã bỏ lỡ một cái gì đó, đó là, dấu hiệu ':' được gọi là * dấu hai chấm * bằng tiếng Anh. Tôi hy vọng nhiều người ở đây tiếp tục bỏ phiếu cho câu trả lời của bạn. > - ( – Vantomex

0

Bạn có thể thực hiện một số Select algorithm để tìm nhanh ra khỏi vị trí, điều này sẽ không làm tăng tốc độ chuỗi là "Đúng", nhưng nó sẽ làm cho nó nhanh hơn một chút.

0

Lấy độ dài chuỗi, sử dụng GetMem để cấp phát bộ nhớ kích thước của chuỗi. FillChar bộ nhớ với char mong muốn. Sau đó, sử dụng CompareMem để so sánh chuỗi và bộ nhớ

6

Bạn đã thực hiện đề xuất của Barry Kelly sai. Khi tôi kiểm tra nó trên Delphi 7, nó thậm chí còn chậm hơn so với triển khai đầu tiên của bạn và nó cho kết quả sai nếu độ dài chuỗi của bạn không chia hết cho 4.

Tôi đã thử nó với chuỗi này: StringOfChar('c', 100000) + 'x'; và hàm mới của bạn trả về đúng AllElementsAreEqual('c', StringOfChar('c', 100000) + 'x') trong khi nó sẽ trả về Sai. Triển khai của bạn chậm hơn vì bạn đang cố gắng làm cho chuỗi của bạn chia hết cho bốn (trong đó bạn thất bại, nhưng bạn có thể tự mình hiểu tại sao nó không thành công) và do đó tạo ra một chuỗi mới cần phân bổ bộ nhớ tốn kém.

Một điều nguy hiểm khác mà bạn làm là để mảng động (mảng số nguyên) trỏ tới một chuỗi. Cả hai đều được nạp lại và điều này có thể dẫn đến kết quả lạ. Hãy làm theo lời khuyên của Barry Kelly và sử dụng một PIntegerArray!

Tôi nghĩ rằng Barry Kelly nghĩa này:

function AllElementsAreEqual(const aElement: Char; const aStr: string): Boolean; 
var 
    lIntArray: PIntegerArray; 
    i: Integer; 
    lTest: Integer; 
begin 
    Result := True; 
    lTest := Ord(aElement) + Ord(aElement) shl 8 + Ord(aElement) shl 16 + Ord(aElement) shl 24; 

    lIntArray := @aStr[1]; 
    for i := 0 to Length(aStr) div 4 - 1 do 
    if lIntArray[i] <> lTest then 
    begin 
     Result := False; 
     Exit; 
    end; 

    for i := Length(aStr) - (Length(aStr) mod 4) + 1 to Length(aStr) do 
    if aStr[i] <> aElement then 
    begin 
     Result := False; 
     Exit; 
    end; 
end; 

NB: Chức năng của bạn trả về True cho chuỗi rỗng, đó là OK?

NB2: Vui lòng ghi điểm cho câu trả lời của Barry Kelly chứ không phải của tôi, bởi vì đây thực sự là một nhận xét quá khổ và không phải là câu trả lời.

+0

+1 Tôi xin lỗi nhưng đêm qua tôi đã làm nhiều bài kiểm tra với các triển khai khác nhau và tôi đã đăng một triển khai cũ của giải pháp được đề xuất (có lỗi), hiện đã được khắc phục. Cảm ơn rất nhiều vì đã tạo ra sự thực hiện tốt hơn đề xuất của Barry. – Salvador

Các vấn đề liên quan