タプルからのJavaScript変数の割り当て


98

Python 2やPython 3などの他の言語では、値を定義してタプル変数に割り当て、次のように値を取得できます。

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

JavaScriptに似たものはありますか?または、配列で醜い方法を実行する必要がありますか?

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

JavaScript 5でPythonタプルをシミュレートするより良い方法はありますか?

更新: ES6に関する回答を参照してください。これは、新しいプロジェクトではCoffeeScriptよりも優先されます。


12
JavaScriptでは、変数を宣言することを忘れないでください。var tuple, name, age;
ŠimeVidas

3
var name=tuple[0], age=tuple[1]; タイピングは少し多いですが、醜いのは誇張かもしれません。
ブレントブラッドバーン2013

回答:


119

Javascript 1.7は、構造化された割り当てを追加しました。これにより、基本的には目的を達成できます。

function getTuple(){
   return ["Bob", 24];
}
var [a, b] = getTuple();
// a === "bob" , b === 24 are both true

5
これは標準ベースのJavaScriptではなく、Mozilla固有の拡張機能です。
ninjagecko 2012

14
@ninjagecko:「JavaScriptは、」Mozillaの実装で、構造化代入割り当ては今後のECMAScript標準の一部になる
Bergi

64
これは実際にはES6の一部です。
Pier Paolo Ramon

9
数年を考えると、私の答えは技術的に正しいものになりましたが、正しいものと役立つものの両方に役立ちません。わーい!
pc1oad1etter 2016

49

あなたは醜い方法でそれをしなければなりません。このようなものが本当に必要な場合は、CoffeeScriptをチェックしてみてください。CoffeeScriptには、Pythonのように見せるための機能や他の多くの機能があります(広告のように聞こえてしまい申し訳ありませんが、私は本当に気に入っています。)


うーん、これは非常に興味深いことです。JavaScriptは明らかなタプルサポートを提供していないようで、関数型プログラミングの激しい期間からタプルの欲求を開発しているため、このシナリオを自分で実行しました。私もこれを見つけましたが、うまくいくかどうかはわかりませんが、タプルのサポートの点で見栄えがしました: cs.umd.edu/projects/PL/arrowlets/api-tuples.xhtml。私は間違いなくCoffeeScriptを見ていきます。
9codeMan9 2013

29

同様のことができます:

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

名前と年齢を属性として参照します

tuple.name 
tuple.age 

5
私は反対投票はしませんが、技術的にはこれは正しくありません。オブジェクトが宣言された後でも、tuple.nameとtuple.ageの値を変更(つまり変更)できます。定義により、不変タイプは定義後に変更できません。これらは、パラメーターとその値の両方を1度だけ宣言できる読み取り専用型のようなものです。
エヴァンプレイス2014

4
@EvanPlaice可変性が問題である場合、次のように使用できますObject.freeze()。つまり、tuple = Object.freeze({ name:'Bob', age:14 })
canon

@canon私は同意します、それはおそらくこのスレッド全体で受け入れられる/正しいアプローチのみです。残念ながら、mcmの答えはオブジェクトをフリーズしないため、まだ変更可能です。
Evan Plaice 2014年

@EvanPlaice可変性の問題の原因はわかりません。元のPythonの例ではタプルは不変ではありません。
Daniel Buckmaster 2015年

@DanielBuckmaster Pythonでのリストとタプルの違いは、リストは変更可能ですが、タプルは変更できないことです。docs.python.org/2/tutorial/…を参照してください。作成後にオブジェクトでObject.freeze()を呼び出さない限り、すべてのJSデータ構造は変更可能であるため、JavaScriptではタプルはネイティブにサポートされていません。
Evan Plaice、2015年

27

この「タプル」機能は、EcmaScript2015では構造化解除と呼ばれ、すぐに最新のブラウザーでサポートされる予定です。現時点では、FirefoxとChromeのみがサポートしています。

しかし、ねえ、トランスパイラーを使用できます。

コードはpythonと同じくらい美しく見えます:

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

console.log(name)
console.log(age)

2
今後の読者へ:この機能は、Chrome 49以降でサポートされています(Mozillaのドキュメントによると)。また、ここではMozillaのドキュメントを使用して互換性をチェックすることができます。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
ジェイミー

12

フリーズされた配列はpythonタプルと同じように動作します:

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

ファンシーでクラスを定義する

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

今日、すべての最新ブラウザーで動作します。


単にconstに設定できませんか?constは不変です。
マークA

2
いいえ。constは再割り当てできません。const tuple = ["Jim"、35];は実行できません。tuple = ["James"、35]。const tuple = ["Jim"、35];を実行できます。tuple [0] = "ジェームズ"; したがって、それは不変ではありません。
マシュージェームスデイビス

6

タプルはJavaScriptではサポートされていません

不変のリストを探している場合は、Object.freeze()を使用して配列を不変にすることができます。

Object.freeze()メソッドはオブジェクトをフリーズします。つまり、新しいプロパティが追加されないようにします。既存のプロパティが削除されるのを防ぎます。また、既存のプロパティ、またはそれらの列挙可能性、構成可能性、または書き込み可能性が変更されるのを防ぎます。本質的に、オブジェクトは効果的に不変になります。このメソッドは、凍結されているオブジェクトを返します。

ソース:Mozilla Developer Network-Object.freeze()

通常どおり配列を割り当てますが、 'Object.freeze()を使用して配列をロックします

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

通常の配列と同じように値を使用します(Pythonの複数割り当てはサポートされていません)。

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

新しい値を割り当てようとする

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

しかし、値は変更されません

> console.log(tuple)
[ 'Bob', 24 ]

補足として、タプルがES6でファーストクラスのサポートを受けることを期待しています。真のネイティブタプル(つまり、異種シーケンス)も速度を向上させます。
Evan Plaice

5

残念ながら、(ECMA | Java)Scriptでそのタプル割り当て構文を使用することはできません。

編集:誰かがMozilla / JS 1.7にリンクしました-これはクロスブラウザでは機能しませんが、それが必要ない場合はあなたの答えがあります。


3

これは実際に実際に使用することを目的としたものではなく、興味深い演習です。JavaScriptのeval関数を使用することがなぜ悪い考えなのかをご覧ください詳細については。

これは、ベンダー固有の拡張機能に頼らずに取得できる最も近いものです。

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

ヘルパー関数:

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(',');
}

任意のスコープで機能することの証明:

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

eval Safariではサポートされていません。


5
+1は非常に賢いので、実際にはこれを使用しないでください:-p
Jamund Ferguson

3

大臣の回答の更新として、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


ES2015より前にこれを行うことができなかった理由はありません...またこれはOPの質問に答えません、彼は構造化を求めました
ThatWeirdo

3

JavaScriptでもタプル型を使用できます。より高次の関数で定義するだけです(学術用語はChurchエンコーディングです)。

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

その点に注意してください Tuple通常のコンストラクタとしては使用されない。ソリューションはプロトタイプシステムにまったく依存せず、高次関数のみに依存します。

タプルArrayのように使用されるs よりタプルの利点は何ですか?教会でエンコードされたタプルは設計によって不変であり、したがって、突然変異によって引き起こされる副作用を防ぎます。これにより、より堅牢なアプリケーションを構築できます。さらに、Arraysをコレクション型(例[a]:)とタプルをさまざまな型の関連データ(例:)として区別するコードについて、より簡単に推論できます(a, b)


1

簡単なJavascriptタプルの実装は次のとおりです。

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.

これは2タプルですが、3、4、5、6などのタプルをサポートするように私の例を変更できます。


実はこれはt-upleではなくペアです。
Pier Paolo Ramon

tupleインスタンスはまだ変更可能であるので、それは技術的にはタプルではありません。証明変更のtuple.Item1 = "Steve"場合console.log()は、出力。
Evan Plaice、2015年

1
それを見つけてくれてありがとう。タプルを不変にするように例を変更しました。
Faris Zacina、2015年

これを変更して任意の長さをサポートするにはどうすればよいですか?
2016年

これはOPの質問には答えません、彼は
解体

0

Pythonのタプルメソッドを追加したMatthew James Davisの回答のバージョンを次に示します。

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)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.