2014-06-05 19 views
5

Alt diziler oluşturmak için kullanılan belgelerin tümü, dizinin bir kopyasını oluşturan slice hakkında görüştüm. Kopyalamadan bir dizi bir dilim oluşturmanın mümkün olup olmadığını merak ediyorum, böylece dilimi değiştirmek orijinal diziyi değiştirir. Örneğin: tamsayı basit Datatype çünküJavaScript alt dizini kopyalanmadan mı?

var foo = [1, 2, 3, 4, 5]; 
var bar = foo.subarray(2, 4); 
console.log(bar); // [2, 3, 4] 
bar[0] = 'hello, world'; 
console.log(bar); // ['hello, world', 3, 4] 
console.log(foo); // [1, 'hello, world', 3, 4, 5] 

cevap

0

sanmıyorum, bu bir nesne içinde rap eğer, bence mümkün olacağını, mümkündür.

function co(value) 
{ 
    var obj = new Object(); 
    obj.data = value; 
    obj.setValue = function(value) 
    { 
     this.data = value; 
    } 
    return obj; 
} 

var foo = [co(1), co(2), co(3), co(4), co(5)]; 
var bar = foo.slice(2, 4); 
console.log(bar); 
console.log(foo); 
bar[0].setValue('hello, world'); 
console.log(bar); 
console.log(foo); 

http://jsfiddle.net/VGLdP/

+0

Evet kullanarak 'slice' istediğim şey için çalışmıyor. Buradaki fikir, * aynı * diziye yeni bir görünüm kazandırmaktır (tek fark başlangıç ​​dizinidir), yeni bir tane oluşturmaz. –

+0

Aslında, setterler ve alıcılar kullanılarak mümkündür. Pratik değil ama mümkün. – Gio

4

Bu kod referansları (işaretçiler) simüle diğer dillerde olduğu gibi:

Array.prototype.subarray = function(i, j){ 
    var self = this, arr = []; 
    for(var n = 0;i <= j; i++, n++){ 
     (function(i){ 
      Object.defineProperty(arr, n, {  //Array is an Object 
       get: function(){ 
        return self[i]; 
       }, 
       set: function(value){ 
        self[i] = value; 
        return value; 
       } 
      }); 
     })(i); 
    } 
    return arr; 
} 


//This is the exact code you have in your question 
var foo = [1, 2, 3, 4, 5]; 
var bar = foo.subarray(2, 4); 
console.log(bar);     // [3, 4, 5] 
bar[0] = 'hello, world';    // some magic happens here 
console.log(bar);     // ['hello, world', 4, 5] 
console.log(foo);     // [1, 2, 'hello, world', 4, 5] 

Demo: http://jsfiddle.net/DerekL/y7z9T/

subarray gelmez İşte

bir çalışma Demosu olduğunu yaratıcı değil e Orijinal Diziyi kopyalayarak yeni bir Dizi; Özel getters ile boş bir Dizi oluşturur. Akılda tutulması gereken bir şey, yeni dizideki değerlerin, bellek yerine orijinal dizideki dizine bağlanmasıdır.

  index 
    0 1 2 3 4 
     ┌────────────┐ 
┌───┬───┬┤───┬───┬───┐│ 
│ 1 │ 2 ││ 3 │ 4 │ 5 ││ 
└───┴───┴┤───┴───┴───┘│ 
     └────────────┘ 
├──── Whole Array ────┤ 
     ├─ SubArray ─┤ 

"Alt dizi", orijinal dizi için bir "pencere" sağlar. Normalde yaptığınız gibi her iki dizide de içeren değerleri değiştirebilir ve alabilirsiniz. Bunlardan herhangi birinin değiştirilmesi her ikisini de etkileyecektir. Ancak, yeni öğeleri "alt diziye" zorlamaya çalışırsanız kötü şeyler olur, bu yüzden yapmayın.

defineProperty hakkında daha fazla bilgi için lütfen visit MDN. Maalesef

+0

Bu, O (n) zamanını alır, ancak bunu O (1) 'de yapabiliriz. –

5

, Derek'in cevap tekrar subarray.get(i) yerine subarry[i] ait olan değerlere erişmek eğer O(1) bunu yapabilir, oysa uzunluğu n bir SubArray oluşturmak için O(n) alır @:

function make_subarray (array, from, to) { 
    return { 
     get: function (i) { 
      return array[i+from] 
     }, 
     length: to - from 
    } 
} 

Böyle kullanır:

for (var i=0; i<subarray.length; i++) { 
    subarray.get(i) 
} 

Yoksa subarray tanımına bir map() işlevi ekleyebilirsiniz:

function make_subarray (array, from, to) { 
    return { 
     ... 
     map: function (f) { 
     for (var i=0; i<this.length; i++) 
      f(this.get(i)) 
     } 
     ... 
    } 
} 

Derek'in yanıtındaki Object.defineProperty(...{get: ...}) numaralı telefona yapılan her çağrı modern tarayıcılarda yavaş, bu nedenle bunlardan kaçınmak çok iyi.

+0

Asıl amacının, orijinal dizideki aynı bellek parçasına referans veren bir alt diziyi simüle ederken yerel sözdizimini yeniden kullanmak olduğuna inanıyorum. "Alt dizinin" oluşturulması sırasında asimptotik olarak daha yavaş olabileceğine katılıyorum, ancak büyük bir veri setini kullanmıyorsanız (bu durumda daha iyi bir veri yapısı seçin!) Pratikte gözle görülür bir performans farkı olacağından şüpheliyim. –

+1

Kopyadan kaçınmanın nedeni dizinin uzun olması durumunda, bunu O (1) içinde yapmak elbette tam bir noktadır. –

+0

Emin değilim ama her dizi erişimini bir işlev çağrısı olarak değiştirdiğinizde performans sorunları olabilir. – CMCDragonkai

İlgili konular