简体   繁体   中英

Push to array with index method (JavaScript)

I am having difficulty pushing objects to an array of arrays via indices. Find below my current (awfully duplicative code) which reads through a CSV file's lines (Format: Date, reasonCode), and then creates FROM and TO (date) pairs depending on the reasonCode. This array is then used for Highcharts (Gantt chart). Please note the fromto1 and fromto2 arrays.

csv = csv.split(/\n/g);
var fromto1 = [];                   //array of FROM and TO pairs of code 1
    fromto2 = [];                   //array of FROM and TO pairs of code 2
    count = [];
    lastFrom = [];

for (var i=1;i<3;i++) {                 //set all count and lastFrom variables to 0     //bs
    count[i] = 0;
    lastFrom[i] = 0;
}

jQuery.each(csv, function(i, line) {

    line = line.split(',');                 //splits line, returns array of splitted values
    date = parseInt(line[0], 10)*1000;      //read date from line into string
    reasonC = parseInt(line[2], 10);        //read reasonC from line into string

if (reasonC == "1") {
    count[1]++;
    if (count[1] % 2 !=0){          //if it is an uneven value (FROM values)  
        lastFrom[1] = date;         //temporary save the date in lastFrom[]
    }
    else {                          //if it is an even value (TO value), push the pair
        fromto2.push({ 
            from: lastFrom[1],
            to: date
        });
    }   
}

if (reasonC == "2") {
    count[2]++;
    if (count[2] % 2 !=0){          
        lastFrom[2] = date;         
    }
    else {                          
        fromto3.push({ 
            from: lastFrom[2],
            to: date
        });
    }
}

Why can't I replace the above code with this (Please note the fromto array of arrays):

csv = csv.split(/\n/g);
var fromto = [];                    
    count = [];
    lastFrom = [];

for (var i=1;i<3;i++) {                 //set all count and lastFrom variables to 0     
    count[i] = 0;
    lastFrom[i] = 0;
    fromto.push(new Array());
    console.log(i+': New Array Pushed');
}

jQuery.each(csv, function(i, line) {

    line = line.split(',');                 //splits line, returns array of splitted values
    date = parseInt(line[0], 10)*1000;      //read date from line into string
    reasonC = parseInt(line[2], 10);        //read reasonC from line into string

    for (var c=1;c<3;c++) {
        if (reasonC == c.toString()) {
            count[c]++;
            if (count[c] % 2 !=0){          //if it is an uneven value (FROM values)  
                lastFrom[c] = date;         //temporary save the date in lastFrom[]
            }
            else {                          //if it is an even value (TO value), push the pair
                fromto[c].push({ 
                    from: lastFrom[c],
                    to: date
                });
            }   
        }
    }
}

I believe the problem is with fromto[c].push({ as it stays blank arrays. I'm still a Jsnoob and couldn't find any answers on other threads, your help would be highly appreciated

There's quite a few things in your JavaScript that can do with some tips on how to do what you want to do using best practices, so an answer + advice.

1) multiple variables in a single declaration are separated by commas, not semi-colos:

var csv = csv.split(/\n/g),
    fromto = [],
    count = [],
    lastFrom = [];

2) Don't use the Array object for making arrays.

fromto.push([]);

3) JS has function scoping only if you use var . Without var , variables are global.

jQuery.each(csv, function(i, line) {
  line = line.split(',');
  var date = parseInt(line[0], 10)*1000,
      reasonC = parseInt(line[2], 10);

4) == is a coercing equality, and will see if there is any way two values can be considered the same. 4 == "4" is true, 4 === "4" is not.

if (reasonC == c) { ...

or

if (reasonC === c.toString()) { ...

5) JavaScript has forEach baked in, why would you use jQuery for something that's part of JavaScript already?

csv.forEach(function(line) {
  ...
});

And then the answer to your question, of course. It looks like you're trying to turn this data:

123,somevalue,1
456,somevalue,2
...

into this structure:

[
  { from: 123, to: 456 },
  { from: ..., to: ...},
  ...
] 

You're relying on the line order to tell you which date is a from and which is a to; that's bound to go wrong, but you know your data best. (If I were writing this, I would operate on the assumption that line ordering is unknown)

var cvs = data.split(",");
    parity = 0,
    fields,
    odd = [],
    even = [],
    fromTo = [];

cvs.forEach(function(line) {
  parity = (parity + 1) % 2;
  fields = line.split(",");
  bin = parseInt(fields[2],10);
  if(parity===1) {
    odd[bin] = fields;
  } else {
    even[bin] = fields;
    fromTo[bin].push({
      from: odd[bin][0],
      to: even[bin][0]
    });
  }
});

Now, this should work but this code is also really scary, because it still relies on line ordering in the CVS file, and without a hard guarantee that this is the case (like preprocessing validation), this (like your code) will do horrendously wrong things the moment two lines are accidentally in the wrong order.

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