Penugasan variabel JavaScript dari tupel

101

Dalam bahasa lain seperti Python 2 dan Python 3, Anda dapat menentukan dan menetapkan nilai ke variabel tuple, dan mengambil nilainya seperti ini:

tuple = ("Bob", 24)
name, age = tuple
print(name)           #name evaluates to Bob
print(age)            #age evaluates to 24

Apakah ada yang serupa di JavaScript? Atau apakah saya hanya harus melakukannya dengan cara yang jelek dengan sebuah array:

tuple = ["Bob", 24]
name = tuple[0]       //name Evaluates to Bob
age = tuple[1]        //age Evaluates to 24

Apakah ada cara yang lebih baik untuk mensimulasikan tupel Python di JavaScript 5?

Pembaruan: Lihat jawaban mengenai ES6, yang seharusnya lebih disukai daripada CoffeeScript untuk proyek baru.

Karl
sumber
12
Dalam JavaScript, jangan lupa untuk mendeklarasikan variabel:var tuple, name, age;
Šime Vidas
3
var name=tuple[0], age=tuple[1]; Ini sedikit lebih banyak mengetik, tapi jelek mungkin berlebihan.
Brent Bradburn

Jawaban:

122

Javascript 1.7 menambahkan tugas yang dirusak yang memungkinkan Anda untuk melakukan apa yang Anda cari.

function getTuple(){
   return ["Bob", 24];
}
var [a, b] = getTuple();
// a === "bob" , b === 24 are both true
pc1oad1etter
sumber
5
Ini bukan javascript berbasis standar, melainkan ekstensi khusus Mozilla.
ninjagecko
14
@ninjagecko: "JavaScript" adalah implementasi Mozilla, dan tugas penghancuran akan menjadi bagian dari standar ecmascript yang akan datang
Bergi
65
Sekarang sebenarnya bagian dari ES6.
Pier Paolo Ramon
10
Diberikan beberapa tahun jawaban saya telah menjadi benar secara teknis tetapi tidak membantu untuk memperbaiki dan membantu. Yay!
pc1oad1etter
49

Anda harus melakukannya dengan cara yang jelek. Jika Anda benar - benar menginginkan sesuatu seperti ini, Anda dapat melihat CoffeeScript , yang memiliki itu dan banyak fitur lain yang membuatnya lebih mirip python (maaf membuatnya terdengar seperti iklan, tapi saya sangat menyukainya.)

Gabi Purcaru
sumber
Hmm, ini cukup menarik, saya hanya menjalankan skenario ini, karena JavaScript tampaknya tidak memberikan dukungan tupel yang jelas, dan berasal dari periode pemrograman fungsional yang intens, Anda mengembangkan kebutuhan akan tupel. Saya juga baru saja menemukan ini, tetapi tidak yakin apakah berhasil, hanya terlihat bagus dalam hal dukungan tupel juga: cs.umd.edu/projects/PL/arrowlets/api-tuples.xhtml . Saya pasti akan melihat CoffeeScript.
9codeMan9
29

Anda dapat melakukan hal serupa:

var tuple = Object.freeze({ name:'Bob', age:14 })

dan kemudian merujuk pada nama dan usia sebagai atribut

tuple.name 
tuple.age 
monika mevenkamp
sumber
5
Saya tidak akan memberi suara negatif tetapi secara teknis ini tidak benar. Anda masih dapat mengubah (yaitu mengubah) nilai tuple.name dan tuple.age setelah objek dideklarasikan. Menurut definisi, tipe yang tidak dapat diubah tidak dapat diubah setelah ditentukan. Mereka seperti tipe hanya-baca di mana parameter dan nilainya hanya dapat dideklarasikan sekali.
Evan Plaice
4
@EvanPlaice jika mutabilitas adalah masalah, Anda dapat menggunakan Object.freeze(), yaitu:tuple = Object.freeze({ name:'Bob', age:14 })
kanon
@ Canon Saya setuju, itu mungkin satu-satunya pendekatan yang dapat diterima / benar di seluruh utas ini. Sayangnya, jawaban mcm tidak membekukan objek sehingga masih bisa berubah.
Evan Plaice
@EvanPlaice Saya tidak melihat dari mana masalah mutabilitas berasal - tupel tidak dapat diubah dalam contoh Python asli!
Daniel Buckmaster
@DanielBuckmaster Perbedaan antara list dan tuple di Python adalah, list bisa berubah sedangkan tuple tidak. Lihat docs.python.org/2/tutorial/… . Tuple tidak didukung secara native di JavaScript karena semua struktur data JS bisa berubah kecuali Anda memanggil Object.freeze () pada objek setelah pembuatan.
Evan Plaice
27

Fitur "tuple" ini disebut penghancuran di EcmaScript2015 dan akan segera didukung oleh browser terbaru. Untuk saat ini, hanya Firefox dan Chrome yang mendukungnya .

Tapi, hei, Anda bisa menggunakan transpiler .

Kode akan terlihat bagus seperti python:

let tuple = ["Bob", 24]
let [name, age] = tuple

console.log(name)
console.log(age)
Adrian
sumber
2
Untuk pembaca selanjutnya: fitur ini didukung di chrome sejak chrome 49 (menurut dokumen Mozilla). Anda juga dapat memeriksa kompatibilitas menggunakan dokumen Mozilla di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Jamie
13

Array beku berperilaku identik dengan tupel python:

const tuple = Object.freeze(["Bob", 24]);
let [name, age]; = tuple
console.debug(name); // "Bob"
console.debug(age); // 24

Bersikaplah mewah dan tentukan kelas

class Tuple extends Array { 
  constructor(...items) { 
    super(...items); 
    Object.freeze(this);
  } 
}

let tuple = new Tuple("Jim", 35);
let [name, age] = tuple;
console.debug(name); // Jim
console.debug(age); // 35
tuple = ["Bob", 24]; // no effect 
console.debug(name); // Jim
console.debug(age); // 25

Bekerja hari ini di semua browser terbaru.

Matthew James Davis
sumber
Tidak bisakah Anda menyetelnya ke sebuah const? Konst itu tidak bisa diubah, bukan?
Tandai A
3
Tidak. Const tidak dapat dialihkan. Anda tidak dapat melakukan const tuple = ["Jim", 35]; tuple = ["James", 35]. Anda dapat melakukan const tuple = ["Jim", 35]; tuple [0] = "James"; Oleh karena itu, ia tidak dapat diubah.
Matthew James Davis
6

Tuple tidak didukung di JavaScript

Jika Anda mencari daftar yang tidak dapat diubah, Object.freeze () dapat digunakan untuk membuat sebuah array tidak dapat diubah.

Metode Object.freeze () membekukan sebuah objek: yaitu, mencegah properti baru ditambahkan padanya; mencegah properti yang sudah ada dihapus; dan mencegah properti yang ada, atau enumerabilitas, konfigurabilitas, atau kemampuan menulisnya, dari perubahan. Intinya, objek dibuat tidak berubah secara efektif. Metode ini mengembalikan objek yang dibekukan.

Sumber: Jaringan Pengembang Mozilla - Object.freeze ()

Tetapkan sebuah array seperti biasa tetapi kunci itu menggunakan 'Object.freeze ()

> tuple = Object.freeze(['Bob', 24]);
[ 'Bob', 24 ]

Gunakan nilai seperti yang Anda lakukan pada array biasa (multi-assignment python tidak didukung)

> name = tuple[0]
'Bob'
> age = tuple[1]
24

Mencoba menetapkan nilai baru

> tuple[0] = 'Steve'
'Steve'

Tapi nilainya tidak berubah

> console.log(tuple)
[ 'Bob', 24 ]
Evan Plaice
sumber
Di samping catatan mudah-mudahan Tuples akan mendapatkan dukungan kelas satu di ES6. Tupel asli sejati (mis. Urutan heterogen) juga akan meningkatkan kecepatan.
Evan Plaice
5

Sayangnya Anda tidak dapat menggunakan sintaks tugas tuple itu di (ECMA | Java) Script.

EDIT: Seseorang yang ditautkan ke Mozilla / JS 1.7 - ini tidak akan berfungsi lintas-browser tetapi jika itu tidak diperlukan maka ada jawaban Anda.

meder omuraliev
sumber
3

Ini tidak dimaksudkan untuk digunakan dalam kehidupan nyata, hanya latihan yang menarik. Lihat Mengapa menggunakan fungsi eval JavaScript adalah ide yang buruk? untuk detailnya.

Ini adalah cara terdekat yang bisa Anda dapatkan tanpa menggunakan ekstensi khusus vendor:

myArray = [1,2,3];
eval(set('a,b,c = myArray'));

Fungsi pembantu:

function set(code) {
    var vars=code.split('=')[0].trim().split(',');
    var array=code.split('=')[1].trim();
    return 'var '+vars.map(function(x,i){return x+'='+array+'['+i+']'}).join(',');
}

Bukti bahwa itu berfungsi dalam lingkup yang sewenang-wenang:

(function(){
    myArray = [4,5,6];
    eval(set('x,y,z = myArray'));
    console.log(y);  // prints 5
})()

eval tidak didukung di Safari.

ninjagecko
sumber
5
+1 untuk menjadi super pintar, namun jangan pernah menggunakan ini dalam kehidupan nyata :-p
Jamund Ferguson
3

Sebagai pembaruan atas jawaban Menteri, Anda sekarang dapat melakukan ini dengan es2015:

function Tuple(...args) {
  args.forEach((val, idx) => 
    Object.defineProperty(this, "item"+idx, { get: () => val })
  )
}


var t = new Tuple("a", 123)
console.log(t.item0) // "a"
t.item0 = "b"
console.log(t.item0) // "a"

https://jsbin.com/fubaluwimo/edit?js,console

Zach Dahl
sumber
Tidak ada alasan mengapa Anda tidak dapat melakukan ini sebelum ES2015 ... Juga ini tidak menjawab pertanyaan OP, dia meminta untuk merusak
ThatWeirdo
3

Anda juga dapat memiliki jenis tuple di Javascript. Tentukan saja dengan fungsi tingkat tinggi (istilah akademisnya adalah pengkodean Gereja):

const Tuple = (...args) => {
  const Tuple = f => f(...args);
  return Object.freeze(Object.assign(Tuple, args));
};

const get1 = tx => tx((x, y) => x);

const get2 = tx => tx((x, y) => y);

const bimap = f => g => tx => tx((x, y) => Tuple(f(x), g(y)));

const toArray = tx => tx((...args) => args);

// aux functions

const inc = x => x + 1;
const toUpperCase = x => x.toUpperCase();

// mock data

const pair = Tuple(1, "a");

// application

console.assert(get1(pair) === 1);
console.assert(get2(pair) === "a");

const {0:x, 1:y} = pair;
console.log(x, y); // 1 a

console.log(toArray(bimap(inc) (toUpperCase) (pair))); // [2, "A"]

const map = new Map([Tuple(1, "a"), Tuple(2, "b")]);
console.log(map.get(1), map.get(2)); // a b

Harap dicatat bahwa Tupletidak digunakan sebagai konstruktor normal. Solusinya tidak bergantung pada sistem prototipe sama sekali, tetapi hanya pada fungsi tingkat tinggi.

Apa keuntungan tupel dibandingkan Arrays digunakan seperti tupel? Tupel yang dikodekan Gereja tidak dapat diubah oleh desain dan dengan demikian mencegah efek samping yang disebabkan oleh mutasi. Ini membantu membangun aplikasi yang lebih kuat. Selain itu, lebih mudah untuk bernalar tentang kode yang membedakan antara Arrays sebagai jenis kumpulan (misalnya [a]) dan tupel sebagai data terkait dari berbagai jenis (misalnya (a, b)).


sumber
1

Berikut adalah implementasi Javascript Tuple sederhana:

var Tuple = (function () {
   function Tuple(Item1, Item2) {
      var item1 = Item1;
      var item2 = Item2;
      Object.defineProperty(this, "Item1", {
          get: function() { return item1  }
      });
      Object.defineProperty(this, "Item2", {
          get: function() { return item2  }
      });
   }
   return Tuple;
})();

var tuple = new Tuple("Bob", 25); // Instantiation of a new Tuple
var name = tuple.Item1; // Assignment. name will be "Bob"
tuple.Item1 = "Kirk"; // Will not set it. It's immutable.

Ini adalah 2-tupel, namun, Anda dapat memodifikasi contoh saya untuk mendukung 3,4,5,6 tupel dll.

Faris Zacina
sumber
Sebenarnya ini bukan t-uple tapi sepasang.
Pier Paolo Ramon
The tuplecontoh masih bisa berubah, sehingga secara teknis tidak tupel. Untuk bukti perubahan tuple.Item1 = "Steve"maka console.log()outputnya.
Evan Plaice
1
Terima kasih telah menemukan itu. Saya telah memodifikasi contoh untuk membuat Tuple tidak dapat diubah.
Faris Zacina
Bagaimana Anda memodifikasi ini untuk mendukung panjang yang berubah-ubah?
aij
Ini tidak menjawab pertanyaan OP, dia meminta untuk merusak
ThatWeirdo
0

Berikut adalah versi jawaban Matthew James Davis dengan metode tuple Python yang ditambahkan:

class Tuple extends Array { 
  constructor(...items) { 
    super(...items); 
    Object.freeze(this);
  }
  toArray() {
    return [...this];
  }
  toString() {
    return '('+super.toString()+')';
  }
  count(item) {
    var arr = this.toArray();
    var result = 0;
    for(var i = 0; i < arr.length; i++) {
       if(arr[i] === item) {
         result++;
       }
    }
    return result;
  }

  

  
}

   let tuple = new Tuple("Jim", 35);
   let [name,age] = tuple;

console.log("tuple:"+tuple)
console.log("name:"+name)
console.log("age:"+age)

Nirwana
sumber