2016-09-25 3 views
0

Я новичок в javascript и довольно давно изучаю, но не могу понять этот синтаксис. Когда я пытаюсь нажать массив в другой массив, он подталкивает элементы индивидуально, а не создает массив массивов, как я хочу.JavaScript-инициализация/добавление/обновление массива массивов

То, что я пытаюсь сделать:

lastTimes как массив массивов:

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

если: IDandTime = [5, 5959393]

Append IDandTime в lastTimes как массив:

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]] 
Будет

любой ум помогает мне здесь, пожалуйста? Я пробовал много комбинаций синтаксисов и не могу понять это правильно, и мне не удалось найти правильный поисковый запрос, чтобы найти существующий ответ. Любые предложения приветствуются.

EDIT:

код:

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

результат:

lastTimes = [1, 5935935] 

Результат я хочу:

lastTimes = [[1, 5935935]] 

EDIT2:

Хорошо, вот полная функция, с которой я работаю. У меня есть сервер node.js с последовательным модулем XBee и несколькими датчиками температуры Arduino с последовательными модулями XBee. У меня есть механизм рукопожатия, но я пытаюсь добиться проверки ошибок, когда выпадают узлы, поэтому их устаревшие данные больше не используются. Я чувствую, что это действительно просто проблема с базовым синтаксисом 2D-массива.

// 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, 59395]' then 'lastTimes.push (IDandTime)', который вместо того, чтобы приводить к 'lastTimes = [[1,59395]]', приводит к ' lastTimes = [1, 59395] ' – 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] ', так что мне не нужно было« ломать », но я думаю, что либо сработает. – Austin

+0

Это еще одна проблема, которая у вас есть. Если вы также посмотрите на https://www.npmjs.com/package/serialport, вы увидите вариант выполнения этого разделения для вас: 'parser: SerialPort.parsers.readline ('\ n')'. Но ваш код по-прежнему будет иметь указанную проблему. «Break» необходим, чтобы остановить цикл, так как вам не нужно продолжать искать, как только вы найдете то, что хотите. Даже если вы используете другую переменную для хранения 'i'. – Xotic750

+0

@Jake, массивы в JS не присваивают по умолчанию первый элемент, а 'String.prototype.split()' всегда возвращает Array и Array, не равный String (хотя строка и массив имеют много общего), поэтому, если Параметр 'data' действительно представляет собой строку (которая, очевидно, есть), то' buffer0 == "ВЕЩАНИЕ" 'возможно, никогда не будет оцениваться как true. – 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]; 
}); 

И для поиска значения по идентификатору просто:

var value = lastTimes[id]; 
+0

'Object.create (null);' может быть упрощено до ** '{}' **. 'Object.create()' имеет смысл, если вы хотите создать объект с некоторым прототипом. Если вы хотите объект с 'prototype = null', то' {} 'делает именно этот объект. – Vaclav

+0

Это неправда. {} создаст объект с помощью функции «Объект как конструктор», и полученный объект будет «наследовать» функции типа «hasOwnProperty». Попробуйте: console.log ({}. HasOwnProperty) console.log (Object.create (null) .hasOwnProperty) –

+0

Вы правы. Оба метода создают новый 'object' без' prototype', но вывод 'Object.create (null)' также имеет конструктор === undefined', что интересно, и я этого не знал. Но у него очень мало последствий (даже цикл 'for ... in' работает одинаково - вам не нужно использовать' hasOwnProperty() '), поэтому я не вижу стимула использовать более подробные и менее знакомые объекты .create (null) ', или я ошибаюсь? – Vaclav

Смежные вопросы