2016-09-25 20 views
0

我是JavaScript新手,并且一直在研究相当长的一段时间,但无法弄清楚这种语法。当我尝试将数组推入另一个数组时,它会单独推送这些元素,而不是像我想要的那样创建一个数组数组。JavaScript初始化/附加/更新数组数组

我想要做的事:

lastTimes为数组的数组:

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

如果:IDandTime = [5, 5959393]

追加IDandTimelastTimes作为数组:

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

或ID (IDandTime[0])已经存在,更新内lastTimes数组的时间:

如果IDandTime = [1, 50305240] 更新ID为1的时候50305240:

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

有人介意帮我在这里吗?我已经尝试过很多种语法组合,并且无法做到正确,我也没有成功找出适当的搜索词来找到已有的答案。任何建议,非常感谢。

编辑:

代码:

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

结果:

lastTimes = [1, 5935935] 

结果我想:

lastTimes = [[1, 5935935]] 

编辑2:

好吧,这里是我正在使用的全部功能。我有一个带有XBee串行模块的node.js服务器,以及几个带有XBee串行模块的Arduino温度传感器。我有一个握手机制工作,但我试图实现错误检查节点何时退出,所以他们的陈旧数据不再使用。尽管如此,我觉得这实际上只是基本的二维数组语法的一个问题。在寻找正确的语法从我的最后一次尝试

// 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

我没有发布代码,因为它有很多不相关的部分混合在一起(使用node.js作为无线模块的服务器),我认为它会混淆实际问题,我想我在帖子中已经说明了这一点。在大多数情况下,我尝试过很多'IDandTime = [1,539395]'then lastTimes.push(IDandTime)'的组合,而不是导致'lastTimes = [[1,59395]]'产生' lastTimes = [1,539395]' – Austin

回答

2

首先,如果data是字符串,然后调用data.split('\n')返回数组(见String.prototype.split()。),所以每个进行比较if (buffer0 == "BROADCASTING")评估为false。你可能想比较第一行的数据,第一行在buffer0[0],所以写出条件if (buffer0[0] == ...)

然后,你必须在代码中的错误

// If preexisting node, update preexisting node time 
else if (oldNode == 1) { 
    lastTimes[i][1] = IDandTime[1]; 
} 

你在哪里使用可变i从循环,但由于循环不与break关键字终止,循环总是在整个阵列和循环后去已完成,变量i设置为lastTimes.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]'索引吗?因为它似乎仍在工作,尽管我意识到这确实看起来像一个问题。对于第二期,谢谢。我的意思是使用'nodeIndex = i',然后'lastTimes [nodeIndex] [1]',这样我就不需要'bre​​ak'了,但是我想两者都可以工作。 – Austin

+0

这是另一个问题,你有。如果您还查看https://www.npmjs.com/package/serialport,您将看到一个选项来为您执行此分割,即解析器:SerialPort.parsers.readline('\ n')'。但是你的代码仍然会遇到上述问题。 “休息”是必要的,以停止循环,因为你不需要继续寻找,一旦你找到你想要的。即使你使用另一个变量来存储'i'。 – Xotic750

+0

@Jake,JS中的数组不会默认为第一个元素,并且'String.prototype.split()'总是返回一个Array并且Array不等于String(尽管string和array有很多共同之处),所以如果'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方法,但是完全可以是shimmable。否则,这是ES3。我也有一个例子,但我希望OP首先展示他们的问题。 :) – Xotic750

2

你可以使用一个纯粹的对象(不包括原型),而不是一个数组,像这样:

var lastTimes = Object.create(null); 

,而是推一个元组,你可以只设置此对象的属性。这样,您就不必处理更新或手动追加,一切都只是自动工作,像这样:

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(); 

遍历值:

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

并通过ID是查找一个值只是:

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)'的输出也有'构造函数=== undefined',这很有趣,我不知道。但它的后果很少,(即使'for ... in'循环的工作方式相同 - 您不必使用'hasOwnProperty()'),所以我看不到使用更详细和不太熟悉的Object的动机.create(null)',还是我错了? – Vaclav