Home > Mobile >  creating object in js/jQuery creates undefined
creating object in js/jQuery creates undefined

Time:11-05

The code below gives a final undefined part...trying to figure where the undefined part is created. Any thoughts?

jQuery(document).ready(function() {
  console.log("ok");
  var object = {};
  var text = `#DATA1 1000
#DATA2 1000
#DATA3 2000
#DIM 1 "test"
#DIM 6 "test2"`;
  var lines = text.split('\n');
  for (var line = 0; line < lines.length; line  ) {
    //console.log(lines[line]);

    if (lines[line].startsWith("#DIM")) {
      //console.log(lines[line]);
      var myRegexp = /[^\s"] |"([^"]*)"/gi;
      var row = [];
      do {
        //Each call to exec returns the next regex match as an array
        var match = myRegexp.exec(lines[line]);
        if (match != null) {
          //console.log(match);
          row.push(match[1] ? match[1] : match[0]);
          object[row[1]] = {
            namn: row[2]
          };
        }
        //console.log(row);
      } while (match != null);
    }
  }
  console.log(object);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Here's a fiddle.

CodePudding user response:

The problem is that on your first pass, row has only one element in it (row[0]), so row[1] and row[2] are both undefined.

I think the goal of this code is to build an object with properties derived from the #DIM 1 "test" and #DIM 6 "test"2 lines, giving the properties the names "1", "2", etc. with the values of the text in quotes. If so, you don't need row at all, see comments:

const text = `#DATA1 1000
#DATA2 1000
#DATA3 2000
#DIM 1 "test"
#DIM 6 "test2"`;
const object = {};
// Use multiline flag so `^` matches start-of-line and
// $ matches end-of-line
const rexParseLine = /^#DIM\s (\S )\s "([^"] )"\s*$/gm;
let match;
while ((match = rexParseLine.exec(text)) !== null) {
    object[match[1]] = match[2];
}
console.log(object);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Note that I didn't split the text into lines first, the regular expression can handle working within lines if we use the multiline (m) flag. Here'sa breakdown of the regex:

  • ^#DIM - line starts with #DIM
  • \s - followed by one or more whitespace chars
  • (\S ) - followed by one or more non-whitespace chars that we capture
  • \s - followed by one or more whitespace chars
  • "([^"] )" - followed by "s with text in-between that we capture
  • \s*$ - followed by optional whitespace and end-of-line

The g flag lets use use it in a loop to work through the text, and the m flag, again, changes the meaning of ^ and $.

Side note: In modern environments, we can use named capture groups to make that clearer:

Show code snippet

const text = `#DATA1 1000
#DATA2 1000
#DATA3 2000
#DIM 1 "test"
#DIM 6 "test2"`;
const object = {};
// Use multiline flag so `^` matches start-of-line and
// $ matches end-of-line
const rexParseLine = /^#DIM\s (?<key>\S )\s "(?<value>[^"] )"\s*$/gm;
let match;
while ((match = rexParseLine.exec(text)) !== null) {
    const {key, value} = match.groups;
    object[key] = value;
}
console.log(object);
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>


But I have to admit it's not clear to me why you were allowing for the first capture group to be empty, so that may need tweaking.

  • Related