3

I'm trying to access an object within another object using an object key. I'm concatenating the values of a group of <select> elements to build a string that matches the key. Unfortunately this never works. Here's the code below:

    var valueKeyString = "";
    $(".keySelector").each(function(){
        valueKeyString += $(this).val();
    });
    if (geoAttrs[selectedGeoAttr].rowCol == "row") {
        mapData = rowValueGroups[valueKeyString];
    } else if (geoAttrs[selectedGeoAttr].rowCol == "col") {
        mapData = colValueGroups[valueKeyString];
    } 

After trying a good number of things I tested the strings character by character using charCodeAt():

    var test1 = valueKeyString;
    for (var i = 0, len = valueKeyString.length; i < len; i++) {
      test1 += valueKeyString.charCodeAt(i)+" ";
    }
    if (geoAttrs[selectedGeoAttr].rowCol == "row") {
        Object.keys(colValueGroups).forEach(function(group) {
            var test2 = group;
            for (var i = 0, len = group.length; i < len; i++) {
              test2 += group.charCodeAt(i)+" ";
            }
            console.log(test1);
            console.log(test2)                
        })

        mapData = colValueGroups[valueKeyString];
    } 

My concatenated strings all had an extra character with a charCode of 0 at the point of concatenation. Couldn't figure out why it was there or how to get rid of it using a regEx or str.replace(). Ended up with an ugly but functional solution where I just test the object keys to see if they contain the values from the <select> elements:

    var valueKeys = [];
    $(".keySelector").each(function(){
        valueKeys.push($(this).val());
    });
    if (geoAttrs[selectedGeoAttr].rowCol == "row") {
        Object.keys(colValueGroups).forEach(function(group) {
            var groupHasAllKeys = true;
                valueKeys.forEach(function(key) {
                    if (group.indexOf(key) == -1 ) {
                        groupHasAllKeys = false;
                    }
                });
            if(groupHasAllKeys) {
                mapData = colValueGroups[group];
            }  
        });
    } else if (geoAttrs[selectedGeoAttr].rowCol == "col") {
        Object.keys(rowValueGroups).forEach(function(group) {
            var groupHasAllKeys = true;
                valueKeys.forEach(function(key) {
                    if (group.indexOf(key) == -1 ) {
                        groupHasAllKeys = false;
                    }
                });
            if(groupHasAllKeys) {
                mapData = rowValueGroups[group];
            }  
        });
    } 

There's got to be a better way, right? What the hell is going on here?

EDIT: rowValueGroups might look something like this:

{
  "35_to_44_yearsMale": {
    "4654387684": {
      "value": 215
    },
    "4654387685": {
      "value": 175
    },
    "4654387686": {
      "value": 687
    },
    "4654387687": {
      "value": 172
    }
  },
  "45_to_54_yearsMale": {
    "4654387684": {
      "value": 516
    },
    "4654387685": {
      "value": 223
    },
    "4654387686": {
      "value": 54
    },
    "4654387687": {
      "value": 164
    }
  }
}

valueKeyString should be "45_to_54_yearsMale" or the like.

This is survey data. I'm extracting the rowValueGroups data from the output of a nicolaskruchten/pivottable custom renderer. (Specifically from the pivotData.tree object if you're curious). I'm not looking to alter the pivottable core to change how those keys are formatted, so I just figured I'd concatenate a couple of values from a select element to make it work.

Here's part of the console output from the tests above:

35_to_44_yearsMale51 53 95 116 111 95 52 52 95 121 101 97 114 115 0 77 97 108 101
35_to_44_yearsMale51 53 95 116 111 95 52 52 95 121 101 97 114 115 77 97 108 101

First line is the test done on valueKeyString and the second on one of the keys from rowValueGroups. Note that the initial string looks identical, (the Firefox console actually outputs a little character-not-found square in between "years" and "Male" for the valueKeyString one) but the charCodeAt() turns up that weird 0 character at the point of concatenation.

dave
  • 2,762
  • 1
  • 16
  • 32
  • 1
    An example of values would be helpful, for `valueKeyString` and `rowValueGroups`. Would make it easier to get an idea of what you're trying to achieve – MDEV Sep 26 '15 at 22:57
  • Added details in an Edit. – dave Sep 26 '15 at 23:42
  • What if you just cleaned the string after your each? Like `valueKeyString = valueKeyString.replace(/[^a-z0-9_-]+/gi,'')` – MDEV Sep 27 '15 at 09:10
  • Gave it a try. It doesn't clean out that weird character. It seems like regular expressions and the like don't actually recognize it as a character so they can't get rid of it. Nevertheless it seems enough to keep the strings from matching. – dave Sep 27 '15 at 15:16
  • Can you give us a reproducible demo on jsfiddle? I am particularly interested in the html for the keySelector elements. – Sheepy Oct 26 '15 at 02:03
  • @dave: when you can, let me know if the solutions proposed works for you (if they are not tonreach a working solution can be useful to provide a relevant extract of the source html, as stated by Sheepy). Thank you! – Giuseppe Ricupero Oct 26 '15 at 08:51
  • I'll see if I can't reproduce this on JSfiddle. The keySelector elements are all being created dynamically so I'm not sure if the results will be the same. This project may be open-sourced at some point which will make it easier for me to share the code publicly, but right now I have to be careful about how much I expose. – dave Oct 26 '15 at 18:34
  • I think @Sheepy raised a good point about the elements with keySelector class. You may have already checked prior posting, but just in case: did you make sure the `null` characters are not already there? (e.g. C uses the null character as the end of string - could be worth outputting the charCodes of each value right away) or if you get undesired elements when calling `$(".keySelector")`? (could be worth checking for their count) – ghybs Oct 28 '15 at 11:57

3 Answers3

1

You have null characters in your string. This regex will remove them:

valueKeyString = valueKeyString.replace( /\0/g, '' )

Reference: Removing null characters from a string in JavaScript

Community
  • 1
  • 1
Tyler Eich
  • 4,239
  • 3
  • 21
  • 45
0

If you identify the char code you can try to replace it using exactly its code:

var valueKeyString = "";
$(".keySelector").each(function(){
    valueKeyString += $(this).val();
});
valueKeyString = valueKeyString.replace(new RegExp(String.fromCharCode(0),"g"),'');

Or presuming the string already comes \0-terminated directly from the jquery $(this).val() you can try another approach:

var valueKeyString = "";
$(".keySelector").each(function(){
    s = $(this).val();
    if ( s.charCodeAt(s.length - 1) == 0 )
        s = s.substring(0, s.length - 1);
    valueKeyString += s;
});

The above snippet check if the last char of each freshly obtained string from $(this).val() is null-terminated (just to be sure) and remove the last char with substring().

Giuseppe Ricupero
  • 6,134
  • 3
  • 23
  • 32
  • Neither solution will effectively remove the weird 0 character. It's as if it's not a real character, just something else there that returns a char code of 0. I haven't been able to find any effective way of removing it. – dave Oct 26 '15 at 18:28
-1

Since you are using jQuery you can try trim():

var valueKeyString = "";
$(".keySelector").each(function(){
    valueKeyString += $(this).val().trim();
});
Tiago Romero Garcia
  • 1,068
  • 9
  • 11