0

I'm new to Javascript and am having trouble with a function I wrote. I'm using array.reduce() to do the job, but it is failing on Windows (testing on Mac works fine).

The file I have is formatted like this:

ford.car.focus.transmission=standard
ford.car.focus.engine=four-cylinder
ford.car.focus.fuel=gas

ford.car.taurus.transmission=automatic
ford.car.taurus.engine=V-8
ford.car.taurus.fuel=diesel

purchased=Ford Taurus

I would like to have the structure look like this:

{ ford:
  { car:
    { focus:
      {
        transmission: 'standard',
        engine: 'four-cylinder',
        fuel: 'gas'
      }
    }
    { taurus:
      {
        transmission: 'automatic',
        engine: 'V-8',
        fuel: 'diesel'
      }
    }
  }
  purchased: 'Ford Taurus'
}

I'm storing file lines in an array, splitting on '\n'. I'm trying to write a method that would be called in a loop, passing my global object like this:

var hash = {};
var array = fileData.toString().split("\n");
for (i in array) {
  var tmp = array[i].split("=");
  createNestedObjects(tmp[0], tmp[1], hash);
}

My current function looks like this:

function create_nested_object(path, value, obj) {
  var keys = path.split('.');
  keys.reduce(function(o, k) {
    if (k == keys[keys.length-1]) {
      return o[k] = value;
    } else if (o[k]) {
      return o[k];
    } else {
      return o[k] = {};
    }
  }, obj);
}

I would like to turn this into a for loop. I have new code that looks like this (I tried converting the array.reduce() code):

function create_nested_object(path, value, obj) {
  var keys = path.split('.');

  for (var i = 0; i < keys.length; i++) {
    if (keys[i] == keys[keys.length-1]) {
      obj[keys[i]] = value;
    } else if (obj[keys[i]] == keys[i]) {
      obj;
    } else {
      obj = obj[keys[i]] = {};
    }
  }
}

But it only returns the last items in each nest:

{
  "ford": {
    "car": {
      "taurus": {
        "fuel": "diesel"
      }
    }
  },
  "purchased": "Ford Taurus"
}

I know I'm missing something, but I can't figure out what's wrong. Any help would be appreciated!

Related question: Javascript - Parsing INI file into nested associative array

Community
  • 1
  • 1
jbmoon
  • 129
  • 1
  • 11
  • 1
    Why not store your data in a format that has existing parsing methods like JSON (almost what you have now anyway)? There's no need to invent your own data format. Either way it may have something to do with the line endings you're splitting at which are different on different OS's (I'm far from an expert with that stuff though). – Marty Apr 19 '16 at 23:54
  • @Marty is correct. In windows you will need to use "\r\n". – It-Z Apr 19 '16 at 23:59
  • I need to use this file format because it's hooking to a legacy application. – jbmoon Apr 20 '16 at 00:15
  • Ahh, that is unfortunate. – Marty Apr 20 '16 at 01:38

2 Answers2

0

EDIT to use os.EOL

solution in the comments: In the OP code:

var array = fileData.toString().split("\n");

And, as @Marty suggested, Needs to be:

var array = fileData.toString().split(os.EOL);

In Windows.

It-Z
  • 1,961
  • 1
  • 23
  • 33
0

The EOL answer is a good one, so I am giving it the upvote. In answer to my question about why my function was failing is that it had nothing to do with Windows. The issue was that the file on the Windows machine had some duplication in the keys that caused the function to fail.

ford.car.focus.transmission=standard
ford.car.focus.engine=four-cylinder
ford.car.focus.engine.type=big
ford.car.focus.fuel=gas

In the above example, the engine property was being set as a value (four-cylinder), and then on the next iteration of the function it was trying to deal with the fact that there was another (nest) for engine (type=big). Because an object can't have the same key twice, it was causing the function to die.

Thanks to everyone for responding!

jbmoon
  • 129
  • 1
  • 11