2016-09-25 15 views
0

私はjavascriptを使い慣れていて、かなり長い間研究していますが、この構文を理解することはできません。配列を別の配列にプッシュしようとすると、配列の配列を作成するのではなく、要素を個別にプッシュします。JavaScriptを初期化/追加/更新する配列の配列

lastTimes = [[1, 12435235], [2,443531923], [3,4925951], [5, 5959393]] 
IDandTime = [5, 5959393]

が配列としてlastTimesIDandTimeを追加します。

lastTimes = [[1, 12435235], [2,443531923], [3,4925951]] 

場合

:配列の配列として

lastTimes:私は何をしようとしている

またはIDの場合(IDandTime[0])は、すでにlastTimes以内に、そのアレイの時刻を更新し、存在している:

IDandTime = [1, 50305240] 更新ID 1の時間ならば50305240へ:

lastTimes = [[1, 50305240], [2,443531923], [3,4925951], [5, 5959393]] 

誰もがここで私を助けてください気にしませんか?私はシンタックスの多くの組み合わせを試してきましたが、それを正しく得ることはできませんし、既存の答えを見つけるために適切な検索語を見つけ出すことにも成功していません。どんな提案も大歓迎です。

EDIT:

コード:

var lastTimes = []; 
var IDandTime = [1, 5935935]; 
lastTimes.push(IDandTime); 

結果:

lastTimes = [1, 5935935] 

私が望む結果:

lastTimes = [[1, 5935935]] 

EDIT2:

ここでは、私が使用している機能がすべてあります。私は、XBeeシリアルモジュールを備えたnode.jsサーバと、XBeeシリアルモジュールを備えたいくつかのArduino温度センサを持っています。私はハンドシェイクの仕組みを働かせていますが、ノードがドロップアウトしたときのエラーチェックを達成しようとしています。そのため、失効したデータはもはや使用されません。私はこれが実際には基本的な2次元配列構文の問題であるように感じます。適切な構文を見つけることで私の最後の試みから

// Open a new serial port connection 
sp.on("open", function (err) { 
    if (err) { 
     return console.log('Error opening port: ', err.message); 
    } 
    console.log('open'); 


    var nodeCount = 0; 
    var nodes = []; // get rid of after debugging 
    var lastTimes = []; 
    lastTimes[0] = [0,0]; // initalize as 2D array for later 


    // Grab data from buffer 
    sp.on('data', function(data) { 
     // Initialize time Object 
     var time = new Date(); 
     // Split incoming data by newline 
     var buffer0 = data.split('\n'); 

     // New node handshake initiation received 
     if (buffer0 == "BROADCASTING") { 
      nodeCount++; 
      var sendID = nodeCount.toString(); 
      sp.write(sendID); 
      console.log("Broadcast received. Sending identifier #" + sendID); 
      nodes.push(nodeCount); 
     } 

     // Preconnected node data received 
     if ((buffer0 != "BROADCASTING") && (nodeCount > 0)) { 
      var receiveTime = time.getTime(); 
      // [ID, Temp] touple 
      var nodeData = buffer0[0].split(" "); 
      console.log("NodeID: " + nodeData[0] + " Temp(F): " + nodeData[1]);   
      // [ID, Time] touple 
      var IDandTime = []; 
      IDandTime.push(nodeData[0]); 
      IDandTime.push(time.getTime()); 
      console.log("IDandTime: " + IDandTime); 

      // Check for preexisting node ID 
      var oldNode = 0; 
      var nodeIndex = 0; 
      for (var i = 0; i < lastTimes.length; i++) { 
       if (lastTimes[i][0] == IDandTime[0]) { 
        oldNode = 1; 
        nodeIndex = i; 
       } 
      } 
      // If new node, add new node data to lastTimes (list of [ID, Time] touples) 
      if (oldNode == 0) { 
       lastTimes[lastTimes.length] = IDandTime; 
       console.log("lastTimes: " + lastTimes); 
      } 
      // If preexisting node, update preexisting node time 
      else if (oldNode == 1) { 
       lastTimes[i][1] = IDandTime[1]; 
      } 




     } 



    }); 
}); 

エラー:

   lastTimes[i][1] = IDandTime[1]; 
           ^

TypeError: Cannot set property '1' of undefined 
+1

を欲しいです。 – vlaz

+0

ES6 [MAP](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map)をここで使用してください。たとえそれを行う方法としてちょうど参照。 – Xotic750

+0

実際の問題を難読化すると思っていたので、無関係な部分が混在しているので(コードを投稿していませんでした。ほとんどの場合、 'lasttime = [1,59395]'の結果ではなく、 'IDandTime = [1、59395]'と 'lastTimes.push(IDandTime)'の組み合わせを試してみました。 lastTimes = [1、59395] ' – Austin

答えて

2

dataその後data.split('\n')戻り値Array(参照String.prototype.split()を。)を呼び出し、文字列であるので、あなたのそれぞれが01を比較した場合は、falseと評価されます。データの最初の行を比較したい場合は、最初の行がbuffer0[0]であるため、条件if (buffer0[0] == ...)を記述します。

次にあなたがコード

あなたがループから変数 iを使用しているが、ループは breakキーワードで終了されていないため、ループは常に全体の配列を通って、ループの後に起こっている
// If preexisting node, update preexisting node time 
else if (oldNode == 1) { 
    lastTimes[i][1] = IDandTime[1]; 
} 

にエラーが発生していますが終了すると、変数ilastTimes.lengthに設定されます。これは配列の既存のインデックスではありません。

私はこのようなループ記述します。それはあなたの何をやっていないなぜあなたは私たちにあなたが配列の配列を置くために使用しているコードを与える場合は、私たちはあなたを伝えることができるかもしれない

var IDandTime = []; 
var nodeIndex = nodeData[0]; 
IDandTime.push(nodeIndex); 
IDandTime.push(time.getTime()); 

var foundAtIndex; 
for (var i = 0, l = lastTimes.length; i < l; i++) { 
    if (lastTimes[i][0] === nodeIndex) { 
     foundAtIndex = i; 
     break; 
    } 
} 

if (typeof foundAtIndex === 'undefined') { 
    lastTimes.push(IDandTime); 
} else { 
    lastTimes[foundAtIndex] = IDandTime; 
} 
+0

これはデフォルトで '[0]'インデックスですか?たとえそれが問題のように見えるとしても、とにかく働いているように見えるからです。第2号については、ありがとうございます。私は 'nodeIndex = i'と' lastTimes [nodeIndex] [1] 'を使って' break 'する必要はないようにしましたが、どちらかが動作すると思います。 – Austin

+0

あなたが持っている別の問題です。また、https://www.npmjs.com/package/serialportを見ると、この分割を実行するためのオプション、 'parser:SerialPort.parsers.readline( '\ n')'が表示されます。しかし、あなたのコードにはまだ言及された問題があります。あなたが望むものを見つけたら、あなたが探し続ける必要はないので、ループを止めるためには「休憩」が必要です。別の変数を使って 'i'を保存しても。 – Xotic750

+0

@Jake、JSの配列はデフォルトでは最初の要素にはならず、 'String.prototype.split()'は常にArrayを返し、ArrayはStringと等しくありません(文字列と配列には共通点があります)。 'data'パラメータは実際には文字列です(明らかに)、' buffer0 == "BROADCASTING"はおそらく真と評価されません。 – Vaclav

3

あなたが最初の数は、配列の要素の一部であるかどうかを確認し、元の配列またはプッシュでその要素を変更するfindIndexを使用することができます新しい要素から配列へ。

var lastTimes = [[1, 12435235], [2,443531923], [3,4925951]]; 
 

 
function update(val) { 
 
    var i = lastTimes.findIndex(function(e) { 
 
    return e[0] == val[0]; 
 
    }); 
 

 
    if (i != -1) { 
 
    lastTimes[i][1] = val[1]; 
 
    } else { 
 
    lastTimes.push(val); 
 
    } 
 
} 
 

 

 
update([1, 50305240]) 
 
console.log(lastTimes)

+0

注: 'Array#findIndex'はES6メソッドですが、完全にシームレスです。それ以外の場合はES3です。一例も私は待っていましたが、私はOPが最初に問題を示すことを望んでいました。 :) – Xotic750

2

あなたはこのように、配列の代わりに(プロトタイプなし)純粋なオブジェクトを使用することができます。

var lastTimes = Object.create(null); 

、代わりのタプルを押して、あなただけ設定することができますこのオブジェクトのプロパティあなたが更新または手動で追加処理する必要はありませんこの方法では、すべてがちょうどこのように、自動的に動作:

Object.keys(lastTimes).forEach(id => { 
    var value = lastTimes[id]; 
}); 

とIDがあることで値を検索する:

var receiveTime = time.getTime(); 
// [ID, Temp] touple 
var nodeData = buffer0[0].split(" "); 
console.log("NodeID: " + nodeData[0] + " Temp(F): " + nodeData[1]);   
// [ID, Time] touple 
var IDandTime = []; 
IDandTime.push(nodeData[0]); 
IDandTime.push(time.getTime()); 
console.log("IDandTime: " + IDandTime); 

lastTimes[nodeData[0]] = time.getTime(); 

値を反復処理するにはただ:

まず
var value = lastTimes[id]; 
+0

'Object.create(null);'は** '{}' **に簡略化することができます。 'Object.create()'は、あるプロトタイプでオブジェクトを作成したい場合にのみ意味があります。 'prototype = null'でオブジェクトを望むなら、' {} 'はそのオブジェクトを正確に作成します。 – Vaclav

+0

これは当てはまりません。 {}はObjectをコンストラクタ関数として持つオブジェクトを作成し、結果オブジェクトは 'hasOwnProperty'のような関数を継承します。 試してみてください: console.log({}。hasOwnProperty) console.log(Object.create(null).hasOwnProperty) –

+0

あなたは正しいです。どちらのメソッドも 'prototype'を持たない新しい' object'を生成しますが、 'Object.create(null)'の出力も 'constructor === undefined'となってしまい面白いです。しかし、それは非常に少ない結果しか持っていません(for ... inループは同じ方法で動作します。あなたは 'hasOwnProperty()'を使う必要はありません)、より冗長であまり知られていない 'Object .create(null) '、または間違っていますか? – Vaclav