2012-10-22 11 views
8

Tôi đang cố gắng viết một hàm sẽ lấy một mảng trên mảng đầu vào và trả về mảng, chứa tất cả các tập con có thể của mảng đầu vào (bộ nguồn không có phần tử trống). Ví dụ cho đầu vào: [1, 2, 3] kết quả sẽ là [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]].Bộ nguồn của một mảng trong Delphi

Chức năng này không được công việc trong python:

def list_powerset(lst): 
    result = [[]] 
    for x in lst: 
     result += [subset + [x] for subset in result] 
    result.pop(0) 
    return result 

Nhưng tôi đang tìm để thực hiện nó trong Delphi. Điều này có thể thực hiện theo cách này hay tôi nên tìm một thứ khác?

+1

Nó chắc chắn có thể làm được điều này (nhưng mã có thể sẽ không thể là ngắn ngủi trong Delphi). –

+2

Câu trả lời của tôi ở đây sẽ giúp: http://stackoverflow.com/questions/8316479/combination-without-repetition-of-n-elements-without-use-for-to-do –

Trả lời

6
type 
    TIdArray = array of Integer; 
    TPowerSet = array of TIdArray; 

function PowerSet(Ids: TIdArray): TPowerSet; 
// Implementation loosely based on the explanation on 
// http://www.mathsisfun.com/sets/power-set.html 
var 
    TotalCombinations: Integer; 
    TotalItems: Integer; 
    Combination: Integer; 
    SourceItem: Integer; 
    ResultItem: Integer; 
    Bit, Bits: Integer; 
begin 
    TotalItems := Length(Ids); 

    // Total number of combination for array of n items = 2^n. 
    TotalCombinations := 1 shl TotalItems; 

    SetLength(Result, TotalCombinations); 

    for Combination := 0 to TotalCombinations - 1 do 
    begin 
    // The Combination variable contains a bitmask that tells us which items 
    // to take from the array to construct the current combination. 
    // Disadvantage is that because of this method, the input array may contain 
    // at most 32 items. 

    // Count the number of bits set in Combination. This is the number of items 
    // we need to allocate for this combination. 
    Bits := 0; 
    for Bit := 0 to TotalItems - 1 do 
     if Combination and (1 shl Bit) <> 0 then 
     Inc(Bits); 

    // Allocate the items. 
    SetLength(Result[Combination], Bits); 

    // Copy the right items to the current result item. 
    ResultItem := 0; 

    for SourceItem := 0 to TotalItems - 1 do 
     if Combination and (1 shl SourceItem) <> 0 then 
     begin 
     Result[Combination][ResultItem] := Ids[SourceItem]; 
     Inc(ResultItem); 
     end; 
    end; 

end; 
+1

Tôi đưa ra phương pháp này một shot và sau khi một số thích ứng nó chỉ làm việc! Cảm ơn, bạn là người giỏi nhất. – maciejjo

+0

TotalCombinations: = 2 shl (TotalItems - 1); nên là TotalCombinations: = 1 shl TotalItems; –

+0

@DavidHeffernan Kết quả tương tự, nhưng hợp lý hơn một chút. Đã thay đổi nó. – GolezTrol

2

Câu trả lời khác của tôi là một đoạn mã tôi đã tạo trước đây khi tôi cần ở Delphi 2007. Để làm cho nó chung chung hơn, bạn có thể sử dụng Generics. Bây giờ tôi đã không thực sự sử dụng Generics trước đây, nhưng nó có vẻ như làm việc như thế này. Tôi phải thừa nhận tôi đã phải peek here để kiểm tra cú pháp. Nếu có một cách dễ dàng hơn, tôi hy vọng người khác có thể đăng nó.

Mã thực tế không thay đổi gì, ngoại trừ tên của thông số đầu vào. (Yay, Generics!)

type 
    TGenericArray<T> = array of T; 
    TGenericPowerSet<T> = array of array of T; 

    TPowerSet<T> = class(TObject) 
    public 
    class function Get(a: TGenericArray<T>): TGenericPowerSet<T>; 
    end; 

class function TPowerSet<T>.Get(a: TGenericArray<T>): TGenericPowerSet<T>; 
var 
    TotalCombinations: Integer; 
    TotalItems: Integer; 
    Combination: Integer; 
    SourceItem: Integer; 
    ResultItemIncluded: Integer; 
    Bit, Bits: Integer; 
begin 
    TotalItems := Length(a); 

    // Total number of combination for array of n items = 2^n. 
    TotalCombinations := 1 shl TotalItems; 

    SetLength(Result, TotalCombinations); 

    for Combination := 0 to TotalCombinations - 1 do 
    begin 
    // The Combination variable contains a bitmask that tells us which items 
    // to take from the array to construct the current combination. 
    // Disadvantage is that because of this method, the input array may contain 
    // at most 32 items. 

    // Count the number of bits set in Combination. This is the number of items 
    // we need to allocate for this combination. 
    Bits := 0; 
    for Bit := 0 to TotalItems - 1 do 
     if Combination and (1 shl Bit) <> 0 then 
     Inc(Bits); 

    // Allocate the items. 
    SetLength(Result[Combination], Bits); 

    // Copy the right items to the current result item. 
    ResultItemIncluded := 0; 

    for SourceItem := 0 to TotalItems - 1 do 
     if Combination and (1 shl SourceItem) <> 0 then 
     begin 
     Result[Combination][ResultItemIncluded] := a[SourceItem]; 
     Inc(ResultItemIncluded); 
     end; 
    end; 

end; 

Và sử dụng như thế này:

var 
    p: TPowerSet<String>; 
    a: TGenericArray<String>; 
    r: TGenericPowerSet<String>; 
begin 
    SetLength(a, 2); 
    a[0] := 'aaa'; 
    a[1] := 'bbb'; 
    r := p.Get(a); 

    ShowMessage(IntToStr(Length(r))); 
    ShowMessage(r[1][0]);