Clojure 學習入門(19)—— 數組

一、建立數組css

1.1 從集合建立數組 into-array

into-arrayhtml

(into-array aseq) 
(into-array type aseq)java

演示樣例:git

user=> (into-array [1 2 3])
#<Integer[] [Ljava.lang.Integer;@4b0ea9ba>
user=> (seq (into-array [1 2 3]))
(1 2 3)
github

返回包括aset中所有元素的數組。數組的組件類型爲type(假設指定了type),或aset中第一個元素的類型(假設aset不爲空)。或Object。aset中所有元素的類型必須兼容數組的組件類型。type可以使用基本類型的類對象,好比Integer/TYPE等。算法

Added in Clojure version 1.0 
Source數組


(into-array aseq)ide

1 (into-array [])    ; #<Object[]> - []
2 (into-array [1 2 3])    ; #<Long[]> - [123],注:into-array返回的不是原生數組,而是引用數組

演示樣例:函數

user=> (into-array [])
#<Object[] [Ljava.lang.Object;@26ae533a>
user=> (into-array Integer/TYPE [1 2 3])
#<int[] [I@2cba5bdb>
user=> (into-array Long/TYPE [1 2 3])
#<long[] [J@373c0b53>
user=> (seq (into-array Long/TYPE [1 2 3]))
(1 2 3)
性能

(into-array type aseq)

1 (into-array Integer/TYPE [1 2 3])     ; #<int[]> - [123]
2 ; 等效於(int-array [1 2 3])


1.2 建立空數組 make-array

make-array

(make-array type len) 
(make-array type dim & more-dims)

建立並返回一個指定類型、指定尺寸的數組。需要注意是類對象是必需的。

類對象可以經過導入或全然限定名稱得到。type可以使用基本類型的類對象,好比Integer/TYPE等。

Added in Clojure version 1.0 
Source


(make-array type len)

1 (make-array Integer/TYPE 10)     ; #<int[]> - [0000000000]
2 ; 等效於(int-array 10)

(make-array type dim & more-dims)

1 (make-array Integer/TYPE 2 10)     ;二維數組 #<int[][]> - [[I@4b8bc0fb, [I@442ac57c]
2 (make-array Integer/TYPE 2 2 10)     ;三維數組 #<int[][][]> - [[[I@17f7b44f, [[I@75ebad4]


1.3 建立基本類型數組 int-array

int-array

(int-array size-or-seq) 
(int-array size init-val-or-seq)

建立一個int數組

Added in Clojure version 1.0 
Source

演示樣例:

user=> (int-array 10)
#<int[] [I@6490832e>
user=> (seq (int-array 10))
(0 0 0 0 0 0 0 0 0 0)
user=> (double-array 10 1.24)
#<double[] [D@2f87c55c>
user=> (seq (double-array 10 1.24))
(1.24 1.24 1.24 1.24 1.24 1.24 1.24 1.24 1.24 1.24)

同系列的所有方法

  1. byte-array
  2. short-array
  3. int-array
  4. long-array
  5. float-array
  6. double-array
  7. char-array
  8. boolean-array
  9. object-array*

object-array僅僅有(object-array size-or-seq)使用方法

(int-array size)

1 (int-array 3)     ; #<int[]> - [000]
2 ; 至關於(make-array Integer/TYPE 3)

(int-array seq)

1 (int-array [1 2 3])     ; #<int[]> - [123]
2 ; 至關於(into-array Integer/TYPE [1 2 3])

(int-array size init-val)

1 (int-array 3 5)     ; #<int[]> - [555]

(int-array size seq)

1 (int-array 5 [1 2 3])     ; #<int[]> - [12300]
2 (int-array 5 [1 2 3 4 5 6 7])     ; #<int[]> - [12345]


二、 訪問和改動數組

2.1 訪問數組的值 aget

aget

(aget array idx) 
(aget array idx & idxs)

返回指定索引的值。可用於所有類型的Java數組。(等效於array[idx])

Added in Clojure version 1.0 
Source

1 (let [arrs (into-array
2              [(int-array [1 2 3])
3               (int-array [11 12 13 14 15])])]
4   ; #<int[][]> [[123], [1112131415]]
5   (println (aget arrs 0 2))
6   3
7   (println (aget arrs 1 4)))
8   15

2.2 改動數組的值 aset

aset

(aset array idx val) 
(aset array idx idx2 & idxv)

用指定的元素替代數組中索引位置上的元素。

可用於引用類型的Java數組。

返回val。

Added in Clojure version 1.0 
Source

(aset array idx val)

1 (let [arr (object-array ["A" "B" "C" "D" "E"])
2       ; [A, B, C, D, E]
3       val (aset arr 2 "F")]
4   (println val))
5 ; arr: [A, B, F, D, E]
6 ; val: F

演示樣例:

(let [arr (object-array ["A" "B" "C" "D" "E"])
      val (aget arr 2)
      val2 (aset arr 2 "F")
      ]
      (println val)  ; C
      (println val2) ; F
  )
(aset array idx idx2 & idxv)

01 // Java
02 public static Object[][][] arr3d = {
03             {
04                     {
05                             "A""B""C""D""E"
06                     },
07                     {
08                             "1""2""3""4""5"
09                     }
10             },
11             {
12                     {
13                             'a''b''c''d''e'
14                     },
15                     {
16                             1112131415
17                     }
18             }
19     };// 用Clojure初始化多維數組實在是太蛋疼了
20  
21 ; clojure
22 (let [val1 (aset arr3d 0 0 0 "val1")
23       val2 (aset arr3d 0 1 0 "val2")
24       val3 (aset arr3d 1 0 0 "val3")
25       val4 (aset arr3d 1 1 0 "val4")]
26   (println (java.util.Arrays/toString (aget arr3d 0 0)))
27   (println (java.util.Arrays/toString (aget arr3d 0 1)))
28   (println (java.util.Arrays/toString (aget arr3d 1 0)))
29   (println (java.util.Arrays/toString (aget arr3d 1 1))))
30 ; [val1, B, C, D, E]
31 ; [val2, 2345]
32 ; [val3, b, c, d, e]
33 ; [val4, 12131415]

aset-int

(aset-int array idx val) 
(aset-int array idx idx2 & idxv)

用指定的元素替代數組中索引位置上的元素。

可用於int類型的Java數組。返回val。

Added in Clojure version 1.0 
Source

同系列所有方法

  1. aset-byte
  2. aset-short
  3. aset-int
  4. aset-long
  5. aset-float
  6. aset-double
  7. aset-char
  8. aset-boolean
  9. aset

2.3 計算數組長度 alength

alength

(alength array)

返回Java數組的長度。可用於所有類型的數組。

Added in Clojure version 1.0 
Source

1 (alength (char-array 11 \a))     ; 11
2 ; 等效於(count (char-array 11 \a))

2.4 使用Clojure序列庫

2.4.1 通用版序列庫

1 ; clojure.lang.LazySeq
2 ; clojure.lang.LazySeq

2.4.2 數組專用序列庫 amap, areduce

amap 宏

(amap a idx ret expr)

用表達式expr映射數組a。使用一個索引idx,和一個返回值ret。並將ret初始化爲數組a的克隆,而後將ret的每個元素應用於expr表達式,(用表達式的返回值替換ret當前值)最後返回新的ret數組。

Added in Clojure version 1.0 
Source

1 ; 爲數組的每個值加2
2 (let [arr (int-array [1 2 3])
3       ret (amap arr idx ret (do
4                               (println "=" (vec ret))
5                               (+ 2 (aget ret idx))))]
6   (println (vec ret)))

演示樣例:

(let [arr (int-array [1 2 3])
      ret (amap arr idx ret (do (println "=" (vec ret))
                (+ 2 (aget ret idx)))
                )]
  (println (vec ret))
  )

;= [1 2 3]
;= [3 2 3]
;= [3 4 3]
;[3 4 5]

areduce 宏

(areduce a idx ret init expr)

用表達式expr概括數組a。使用一個索引idx。和一個返回值ret。將ret初始化爲init,將ret設置爲expr表達式每一步的計算結果,最後返回ret。

Added in Clojure version 1.0 
Source

1 ; 計算數組[12, .., 100]每個元素的和
2 (let [arr (int-array (range 1 101))
3       ret (areduce arr idx ret 0 (+ ret (aget arr idx)))]
4   (println ret))
5 5050


三、 其它

3.1 類型轉換 ints

  • bytes `Casts to bytes[]` Added in Clojure version 1.1
  • shorts `Casts to shorts[]` Added in Clojure version 1.1
  • ints `Casts to int[]` Added in Clojure version 1.0
  • longs `Casts to long[]` Added in Clojure version 1.0
  • floats `Casts to float[]` Added in Clojure version 1.0
  • doubles `Casts to double[]` Added in Clojure version 1.0
  • chars `Casts to chars[]` Added in Clojure version 1.1
  • booleans `Casts to boolean[]` Added in Clojure version 1.1

引用類型可以用to-array

3.2 數組克隆 aclone

aclone

(aclone array)

返回Java數組的拷貝。

可用於已知類型的數組。

Added in Clojure version 1.0 
Source


四、總結

生活中一怕沒有選擇。二怕選擇過多。建立數組的方法太多也會使思惟混亂。通常而言對於引用類型的對象,使用集合容器遠優於使用數組。因此使用數組的場景就僅僅有處理基本類型數據(並且對性能有必定要求)的狀況了,所以我的推薦優先使用int-array等方法建立數組。 
花了一天時間,翻了好幾本書。差點兒找遍了與數組相關的所有方法,但願沒有遺漏的。

Clojure數組專題到此爲止,以後會繼續以專題的形式總結其它的API。

========2013/11/4 
Clojure操做多維數組的aset, aget性能簡直讓人沒法直視,用來寫算法仍是算了吧。

========2013/12/8 
直接使用into-array函數返回的不是原生數組,而是一個引用數組。假設要用into-array建立原生數組,必須指定類型(第一個參數)。以前沒注意這個。在《The Joy Of Clojure》中看到。


附錄:

user=> (find-doc "-array")

user=> (find-doc "-array")
-------------------------
clojure.core/boolean-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of booleans
-------------------------
clojure.core/byte-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of bytes
-------------------------
clojure.core/char-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of chars
-------------------------
clojure.core/double-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of doubles
-------------------------
clojure.core/float-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of floats
-------------------------
clojure.core/int-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of ints
-------------------------
clojure.core/into-array
([aseq] [type aseq])
  Returns an array with components set to the values in aseq. The array's
  component type is type if provided, or the type of the first value in
  aseq if present, or Object. All values in aseq must be compatible with
  the component type. Class objects for the primitive types can be obtained
  using, e.g., Integer/TYPE.
-------------------------
clojure.core/long-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of longs
-------------------------
clojure.core/make-array
([type len] [type dim & more-dims])
  Creates and returns an array of instances of the specified class of
  the specified dimension(s).  Note that a class object is required.
  Class objects can be obtained by using their imported or
  fully-qualified name.  Class objects for the primitive types can be
  obtained using, e.g., Integer/TYPE.
-------------------------
clojure.core/short-array
([size-or-seq] [size init-val-or-seq])
  Creates an array of shorts
-------------------------
clojure.core/to-array
([coll])
  Returns an array of Objects containing the contents of coll, which
  can be any Collection.  Maps to java.util.Collection.toArray().
-------------------------
clojure.core/to-array-2d
([coll])
  Returns a (potentially-ragged) 2-dimensional array of Objects
  containing the contents of coll, which can be any Collection of any
  Collection.
nil


參考推薦:

Clojure API之數組操做

相關文章
相關標籤/搜索