简体   繁体   中英

Adding values to existing array of arrays

I'm making an array that will look like this var qwe = [[a,b],[c],[d]] with the purpose of a and b being the identifiers.

a - d are coming from reading the DOM. My current JS is doing what I want it to but I want to combine the similar arrays by their identifiers. Running the below code will give me

qwe =[
[100,200],[3],[2],  
[200, 300],[12],[4],    
[100,200],[2],[6]
]

but I want the final array to add the similar arrays by their identifiers so it will end up looking like (based on previous example)

qwe =[
[100,200],[5],[8],
[200, 300],[12],[4]
]

HTML

<table name="tab" id="tab">
  <tr>
    <th>ID</th>
    <th>Location</th>
    <th>Value</th>
    <th>Other</th>
  </tr>
  <tr>
    <td><input name="itinValue" value="100"></td>
    <td><input name="location" value="200"></td>
    <td><input name="num" value='3'></td>
    <td><input name="other" value='2'></td>
  </tr>
  <tr>
    <td><input name="itinValue" value="200"></td>
    <td><input name="location" value="300"></td>
    <td><input name="num" value='12'></td>
    <td><input name="other" value='4'></td>
  </tr>
  <tr>
    <td><input name="itinValue" value="100"></td>
    <td><input name="location" value="200"></td>
    <td><input name="num" value='2'></td>
    <td><input name="other" value='6'></td>
  </tr>
</table>

JS

var table = document.querySelectorAll('[name="itinValue"]');
var qwe = [];

for(var i = 0; i < table.length; i++) {
  var a = document.getElementsByName('itinValue')[i].value;
  var b = document.getElementsByName('location')[i].value;
  var c = document.getElementsByName('num')[i].value;
  var d = document.getElementsByName('other')[i].value;
  var x = [[a,b],[c],[d]];

  //Compare,find,add here

  //if identifiers do not exist
  qwe.push(x);

}

This is a fiddle to my example that also correctly outputs the html too https://jsfiddle.net/3oge7wxg/125/

It looks like you want something called an associative array, "dict" in python, a key/value pairing, with the keys being your [a,b] part and the values your [c,d] parts.

You can emulate this in JavaScript through objects.

Further reading is here:

You could try to find the item for updating and if not push the new array.

 var table = document.querySelectorAll('[name="itinValue"]'), qwe = [], a, b, c, d, i, item; for (i = 0; i < table.length; i++) { a = +document.getElementsByName('itinValue')[i].value; b = +document.getElementsByName('location')[i].value; c = +document.getElementsByName('num')[i].value; d = +document.getElementsByName('other')[i].value; item = qwe.find(([[l, r]]) => l === a && r === b); if (item) { item[1][0] += c; item[2][0] += d; } else { qwe.push([[a, b], [c], [d]]); } } console.log(qwe); 
 <table name="tab" id="tab"> <tr> <th>ID</th> <th>Location</th> <th>Value</th> <th>Other</th> </tr> <tr> <td><input name="itinValue" value="100"></td> <td><input name="location" value="200"></td> <td><input name="num" value='3'></td> <td><input name="other" value='2'></td> </tr> <tr> <td><input name="itinValue" value="200"></td> <td><input name="location" value="300"></td> <td><input name="num" value='12'></td> <td><input name="other" value='4'></td> </tr> <tr> <td><input name="itinValue" value="100"></td> <td><input name="location" value="200"></td> <td><input name="num" value='2'></td> <td><input name="other" value='6'></td> </tr> </table> 

Version with Map .

 var table = document.querySelectorAll('[name="itinValue"]'), qwe = [], a, b, c, d, i, item map = new Map; for (i = 0; i < table.length; i++) { a = +document.getElementsByName('itinValue')[i].value; b = +document.getElementsByName('location')[i].value; c = +document.getElementsByName('num')[i].value; d = +document.getElementsByName('other')[i].value; item = map.get([a, b].join('|')); if (item) { item[1][0] += c; item[2][0] += d; } else { item = [[a, b], [c], [d]] map.set([a, b].join('|'), item); qwe.push(item); } } console.log(qwe); 
 <table name="tab" id="tab"> <tr> <th>ID</th> <th>Location</th> <th>Value</th> <th>Other</th> </tr> <tr> <td><input name="itinValue" value="100"></td> <td><input name="location" value="200"></td> <td><input name="num" value='3'></td> <td><input name="other" value='2'></td> </tr> <tr> <td><input name="itinValue" value="200"></td> <td><input name="location" value="300"></td> <td><input name="num" value='12'></td> <td><input name="other" value='4'></td> </tr> <tr> <td><input name="itinValue" value="100"></td> <td><input name="location" value="200"></td> <td><input name="num" value='2'></td> <td><input name="other" value='6'></td> </tr> </table> 

I would use objects, just create a composite key:

var table = document.querySelectorAll('[name="itinValue"]');
var qwe = {};

for(var i = 0; i < table.length; i++) {
  var a = document.getElementsByName('itinValue')[i].value;
  var b = document.getElementsByName('location')[i].value;
  var c = new Number(document.getElementsByName('num')[i].value);
  var d = new Number(document.getElementsByName('other')[i].value);

  var key = a + "_" + b;

  previousValue = qwe[key];
  qwe[key] = previousValue ? [previousValue[0] + c, previousValue[1] + d] : [c, d];

}

You can convert to your desired array like so:

Object.keys(qwe).map(key => [key.split("_")].concat(qwe[key]));

https://jsfiddle.net/3oge7wxg/161/

Edit: Number constructors; Added fiddle

There are key facts I am taking note of in your question:

  • you are looping an array of data.
  • you are storing data based on a key which is a tuple.
  • values where key is a match is an addition option.
  • a,b,c,d are all ints,so if these are strings, you would need to run parseint() if they are strings. This can be done by checking if it is currently type is a string, and if so, convert it.

Since it is a tuple and those are not implmented in javascript, you can do something like this.

var m = {};
var table = document.querySelectorAll('[name="itinValue"]');
for(var i = 0; i < table.length; i++) {

  var a = +document.getElementsByName('itinValue')[i].value;
  var b = +document.getElementsByName('location')[i].value;
  var c = +document.getElementsByName('num')[i].value;
  var d = +document.getElementsByName('other')[i].value;

  var key = a.toString() + "-" + b.toString();
  //creates key = "100-200"
  if (m[key]){
    m[key] = [m[key][0] + c, m[key][1] + d]
  }else{
    m[key] = [c,d]
  }
}

in the end, your map will now have unique keys and a map that looks like:

{
  "100-200": [5,8],
  "200-300": [12,4]
}

and if for whatever reason, you need to break up they keys later, you just split on the key. map.keys[index].split("-")

I think this is clean, but if you want to go a bit more, you could turn it into a class.

You then store the information in qwe. If you need to, you can easily convert that from a map to a list, but it depends on your desired implementation goal. The key difference generally is whether or not you wish to maintain order. qwe is populated only with this information, and given your comment based on this being your implementation not the best one, it gives me enough insight to believe that order isnt really as important as preservation of they key data elements, this key/tuple, and 2 values.

If you know the amount of fields per row, here is an alternate way of retrieving your array.

var qwe = {};
var els = document.querySelectorAll('table#tab input');
for (i=0; i<els.length; i+=4) {
    var indexer = i < 4 ? 0 : i;
    var row = {
        a: [
            parseInt(els[indexer].value)
          , parseInt(els[indexer+1].value)
        ]
        , c: parseInt(els[indexer+2].value)
        , d: parseInt(els[indexer+3].value)
    };
    row.key = row.a.join('_');

    if (qwe[row.key]) {
        qwe[row.key][1][0]+=row.c;
        qwe[row.key][2][0]+=row.d;
    } else {
        qwe[row.key] = [row.a, [row.c], [row.d]];
    }
}

console.log( Object.values(qwe) );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM