Это, как правило, не самое эффективное решение, но оно делает то, что мне нужно. Простые тестовые примеры ниже ...
function clone(obj, clones) {
// Makes a deep copy of 'obj'. Handles cyclic structures by
// tracking cloned obj's in the 'clones' parameter. Functions
// are included, but not cloned. Functions members are cloned.
var new_obj,
already_cloned,
t = typeof obj,
i = 0,
l,
pair;
clones = clones || [];
if (obj === null) {
return obj;
}
if (t === "object" || t === "function") {
// check to see if we've already cloned obj
for (i = 0, l = clones.length; i < l; i++) {
pair = clones[i];
if (pair[0] === obj) {
already_cloned = pair[1];
break;
}
}
if (already_cloned) {
return already_cloned;
} else {
if (t === "object") { // create new object
new_obj = new obj.constructor();
} else { // Just use functions as is
new_obj = obj;
}
clones.push([obj, new_obj]); // keep track of objects we've cloned
for (key in obj) { // clone object members
if (obj.hasOwnProperty(key)) {
new_obj[key] = clone(obj[key], clones);
}
}
}
}
return new_obj || obj;
}
Тест циклического массива ...
a = []
a.push("b", "c", a)
aa = clone(a)
aa === a //=> false
aa[2] === a //=> false
aa[2] === a[2] //=> false
aa[2] === aa //=> true
Функциональный тест ...
f = new Function
f.a = a
ff = clone(f)
ff === f //=> true
ff.a === a //=> false
Как объясняется здесь здесь , ключевое различие заключается в том, что flatten
является методом объекта ndarray и, следовательно, может быть вызван только для истинных массивов numpy. Напротив, ravel()
является функцией уровня библиотеки и, следовательно, может быть вызвана на любой объект, который может быть успешно проанализирован. Например, ravel()
будет работать над списком ndarrays, в то время как flatten недоступен для этого типа объекта.
@IanH также указывает на важные различия с обработкой памяти в его ответе.
Текущий API таков:
flatten
всегда возвращает копию. ravel
, когда это возможно, возвращает представление исходного массива. Это не видно на распечатанном выходе, но если вы измените массив, возвращаемый ravel, он может изменить записи в исходном массиве. Если вы измените записи в массиве, возвращенном из сглаживания, этого никогда не произойдет. ravel часто будет быстрее, поскольку копия памяти не будет скопирована, но вы должны быть более осторожны при изменении возвращаемого массива. reshape((-1,))
получает представление всякий раз, когда шаги array, даже если это означает, что вы не всегда получаете смежный массив. a.flatten()
, чтобы получить копию точно , a.ravel()
, чтобы избежать большинства копий, но все же гарантировать, что возвращаемый массив смежный, и a.reshape((-1,))
действительно получить представление всякий раз, когда шаги массива позволяют это, даже если это означает, что вы не всегда получаете смежный массив.
– IanH
17 November 2015 в 21:59
ravel
гарантирует непрерывный массив, и поэтому не гарантируется, что он возвращает представление; reshape
всегда возвращает представление, и поэтому не гарантируется, что он возвращает смежный массив.
– iled
10 February 2017 в 20:49