配列(リスト)をコピーするには (clone) 2016/11/25
配列(リスト)をコピーする方法。
イミュータブルなオブジェクトのコピーは意味がないので、ここではミュータブルなリストのコピーについて。
Go言語 (golang) 2017/07/23
copy
関数を使う。別の配列へのコピーだけでなく、同じ配列の中で別の領域にコピーすることもできる。
arr := []int{0, 1, 2, 3, 4}
copy(arr[0:3], arr[2:5])
fmt.Printf("%#v\n", arr)
// => []int{2, 3, 4, 3, 4}
copy
関数は配列ではなくスライスを受け入れるため、配列をコピーするには arr[:]
などとしてスライスにしたものをcopy
関数に渡す。
Java 2017/07/23
Signature:
void java.lang.System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
別の配列へのコピーだけでなく、同じ配列の中で別の領域にコピーすることもできる。
int[] arr = new int[]{0, 1, 2, 3, 4};
System.arraycopy(arr, 2, arr, 0, 3);
for (int i = 0; i < arr.length; i++) {
System.out.printf("%d: %d\n", i, arr[i]);
}
// 出力例
// 0: 2
// 1: 3
// 2: 4
// 3: 3
// 4: 4
java.lang.System.arraycopy
| Java Platform SE 8 Javadoc
http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#arraycopy-java.lang.Object-int-java.lang.Object-int-int-
PHP 2016/11/25
配列を別の変数に代入するだけでコピーになる。
$src = array(1, 2, 3);
$dst = $src;
$src[0] = 10;
var_export($src);
// 出力結果
// array (
// 0 => 10,
// 1 => 2,
// 2 => 3,
// )
var_export($dst);
// 出力結果
// array (
// 0 => 1,
// 1 => 2,
// 2 => 3,
// )
しかも deep copy になる。
$src = array(1, array(2, 3));
$dst = $src;
$src[1][0] = 20;
var_export($src);
// 出力結果
// array (
// 0 => 1,
// 1 =>
// array (
// 0 => 20,
// 1 => 3,
// ),
// )
var_export($dst);
// 出力結果
// array (
// 0 => 1,
// 1 =>
// array (
// 0 => 2,
// 1 => 3,
// ),
// )
)
PHPでは普通の配列と連想配列は同じものなので、連想配列のコピーも同じ。
Python 2015/04/26
NumPyでない普通の配列であれば以下の書き方を使う。
dst = src[:]
[:]
はスライス表記であり、この書き方で shallow copy が可能。
例
arr1 = [1, 2, 3]
arr2 = arr1[:]
print(id(arr1))
# => 139997756485216
print(id(arr2))
# => 139997756311240
arr2[1] = 20
print(arr2)
# => [1, 20, 3]
# コピー先で書き換えてもコピー元には影響しない
print(arr1)
# => [1, 2, 3]
なお、この書き方はNumPyではコピーにはならずビューを提供するのみになる。
スライス表記を左辺に置いてもコピーにはなるが、左辺の変数が予めなんでもいいのでとにかく何かしらの配列である必要がある。この方法では、コピー先の変数に新しいオブジェクトが代入されるのではなく、既存の配列がコピー元と同じになるように書き換えられる。
dst[:] = src
例
arr1 = [1, 2, 3]
arr2 = [100, 200, 300, 400]
arr2[:] = arr1
print(id(arr1))
# => 139892140826208
print(id(arr2))
# => 139892140652232
arr2[1] = 20
print(arr2)
# => [1, 20, 3]
# コピー先で書き換えてもコピー元には影響しない
print(arr1)
# => [1, 2, 3]
# この方法でコピーするとコピー先のIDは変わらない。
print(id(arr2))
# => 139892140652232
この左辺にスライス表記を使う方法はNumPyでもコピーになるが、コピー前の配列は同じ大きさである必要がある。
または別の方法としては、copy
モジュールがある。
import copy
copy.copy(lst) # shallow copy
copy.deepcopy(lst) # deep copy
copy — 浅いコピーおよび深いコピー操作 | Python 標準ライブラリ
http://docs.python.jp/2.7/library/copy.html
関連
Ruby / JRuby 2014/12/31
Object#clone
または Object#dup
を使う。
shallow copy である。
Array#clone
, Array#dup
| Ruby 2.1 リファレンスマニュアル
http://docs.ruby-lang.org/ja/2.1.0/method/Array/i/clone.html
Perl 2015/03/03
shallow copy の例
my @src = ...;
my @dst = @src
代入するだけでコピーされる。
変数が配列へのレファレンスの場合の例
my $src = ...;
my $dst = [@$src];
デリファレンスしてから配列を生成し直している。
JavaScript 2015/11/13
shallow copy
dst = src.concat();
または
Array.prototype.clone = function(){
return Array.apply(null, this)
}
dst = src.clone();
concat()
というメソッドは配列を連結した新しい配列を生成するメソッドであるが、引数を与えないとコピーの目的でも使える。配列の要素自体はコピーしないので、shallow copyである。
deep copyするトリッキーな方法として一度JSONにしてしまう、というのがある。
dst = JSON.parse(JSON.stringify(src));
遠回りしているような気がしてかなり気持ち悪い。JSONで表現できない値(関数とか)があると、それはコピーできないし、この方法は推奨されない。
JavaScriptのDeepCopyでJSON.parse/stringifyを使ってはいけない | Qiita
http://qiita.com/seihmd/items/74fa9792d05278a2e898