2014-02-08 23 views
3

我想了解如何使用std.container中可用的各種容器結構,但我無法理解如何執行以下操作:D:不清楚如何使用std.container結構

1)如何創建一個空容器?例如,假設我有一個用戶定義的類Foo,並且想要創建一個應該包含Foo對象的空DList。我應該使用什麼語法?

2)假設ab都是DList!int。我嘗試撥打a ~ b,編譯器告訴我我不行。但是,我可以看到DList已重載該運算符。我錯過了什麼?

回答

5

有三種方法來創建一個新的容器,

  1. 統一的方式,使用std.container.make

    auto list1 = make!(DList!int)(); 
    auto list2 = make!(DList!int)(1, 2); 
    
  2. 使用結構初始化語法:

    auto list1 = DList!int(); 
    
  3. 使用類的幫助函數:

    auto tree1 = redBlackTree!int(); 
    auto tree2 = redBlackTree!int(1, 2); 
    

那些之間的區別是,一些數據結構使用的類和一些與結構實現。並且使用make,您不需要知道第一種方式,因爲沒有有效的區別。

關於追加操作符,您需要附加從DList!T開始的範圍,而不是DList!T本身。例如:

上使用一個更完整的例子,檢查以下內容:

import std.container; 
import std.stdio; 

class Foo { 
    int i; 

    this(int i) { 
    this.i = i; 
    } 

    void toString(scope void delegate(const(char)[]) sink) const { 
    // this is a non allocating version of toString 
    // you can use a normal `string toString()` function too 
    import std.string : format; 
    sink("Foo: %s".format(i)); 
    } 
} 

void main() { 
    auto odds = make!(DList!Foo)(); 
    odds.insert(new Foo(3)); 
    odds.insert(new Foo(5)); 
    writeln("Odds: ", odds[]); 

    odds.insertFront(new Foo(1)); 
    writeln("Odds: ", odds[]); 

    auto evens = make!(DList!Foo)(); 
    evens.insert(new Foo(2)); 
    evens.insert(new Foo(4)); 

    writeln("Evens: ", evens[]); 

    odds.insert(evens[]); 
    writeln("Odds then evens: ", odds[]); 

    odds ~= evens[]; 
    writeln("Odds then evens x 2: ", odds[]); 
} 

可以運行這個網上瀏覽:http://dpaste.dzfl.pl/f34b2ec8a445

2
  1. 根據您要使用的容器上,通常有幾種方法來創建它。在DList的情況下,創建包含Foo元素的空DList的最簡單方法是​​
  2. 不幸的是,連接兩個DList對象並不像a ~ b那麼容易。首先,你需要做切片了出來,然後你需要使用~=運營商,所以a ~ b成爲a ~= b

下面是一些代碼:

import std.stdio; 
import std.container; 

class Foo { 
    private int _val; 

    public this(int arg) { _val = arg; } 
    public int val() @property { return _val; } 
    public void val(int arg) @property { _val = arg; } 
} 

int main() { 
    auto foos = DList!Foo(); 
    auto a = DList!Foo(); 
    a.insert(new Foo(5)); 
    auto b = DList!Foo(); 
    b.insert(new Foo(11)); 

    foos ~= a[]; // slice 
    foos ~= b[]; // slice 
    // writeln(foos[0].val); // "Error: no [] operator overload for type DList!(Foo)" 
    writeln(foos.front.val); // prints 5 
    writeln(foos.back.val); // prints 11 

    return 0; 
} 

在我的愚見,DLIST肯定需要改進。 - 例如,你無法獲得它的長度! (沒有評論)如果你看看http://dlang.org/phobos/std_container.html,它清楚地表明容器原語應該有length屬性。但是,它沒有說明應該支持a ~ b!幸運的是,Array!T確實如此。同樣,std.container頁面也聲明c [x]也應該被支持(其中c是一個容器類型)。就DList!而言,它根本行不通。

我虛心地建議你使用Array而不是DList。它應該表現得更好(更容易緩存),它擁有我們真正需要的一切,包括上面提到的長度屬性。

讓我們修改代碼以使用Array:

import std.stdio; 
import std.container; 

class Foo { 
    private int _val; 

    public this(int arg) { _val = arg; } 
    public int val() @property { return _val; } 
    public void val(int arg) @property { _val = arg; } 
} 

int main() { 
    auto foos = Array!Foo(); 
    auto a = Array!Foo(); 
    a.insert(new Foo(5)); 
    auto b = Array!Foo(); 
    b.insert(new Foo(11)); 

    foos = a ~ b; // concatenation works, ah joy! :) 

    writeln(foos[0].val); // indexed access! yeah! prints 5 
    writeln(foos[1].val); // prints 11 

    // Lets the user press <Return> before program returns 
    stdin.readln(); 

    return 0; 
} 

編輯:在IRC上最近的討論提供了一個啓示 - DLIST沒有一定的操作(如索引訪問的),因爲該操作將不能滿足最低的複雜性要求(在std.container網頁上列出)。

+0

如何從std.container數組中刪除元素?就像說最後一個?當我嘗試std.algorithm.remove或linearRemove時,我得到編譯器錯誤。 – AbstractDissonance