3

I found this code in Ruby (from here):

DX = { E => 1, W => -1, N =>  0, S => 0 }

and I was thinking about how to best format it in JS, given that it's lacking a "when" function.

For reference, N, S, E, and W are "directions", and have aliases like so: const N = 1, S = 2, E = 4, W = 8;

I originally wanted to make a quick arrow function, but then went with this:

function DX(dir) {
    if(dir==E) return 1;
    if(dir==W) return -1;
    if(dir==N) return 0;
    if(dir==S) return 0;
}

That looked a little long to me, so I tried to shorten it:

function DX(dir) {
    if(dir==E) return 1;
    if(dir==W) return -1;
    return 0;
}

And then again:

function DX(dir) {
    return dir==E ? 1 : dir==W ? -1 : 0;
}

But now we reach the problem that this code isn't very readable. So I decided to document it:

// returns the distance in x traveled by that direction
// E => 1, W => -1, N =>  0, S => 0
function DX(dir) {
    return dir==E ? 1 : dir==W ? -1 : 0;
}

And then lastly, I converted it to variable syntax and an arrow function:

let DX = (dir) => dir==E ? 1 : dir==W ? -1 : 0;

Now obviously, all of this code works, but my question is as a manner of style, which is considered "best", either in industry, in your opinion, or where you specifically work? I assume readability is above all else, so which code is most readable in your opinion? I prefer the section with the documentation, personally.

Justin
  • 945
  • 12
  • 26

3 Answers3

2

By using an object as suggested above by several users, we can make this code much simpler. However, we ran into the problem of objects using the literal strings "N", "S", "E", and "W" instead of the variables' numeric values 1, 2, 4, and 8.

I found the answer to this problem on SO which is just adding square brackets (in ES6):

const N = 1, S = 2, E = 4, W = 8;
const DX = { [E]: 1, [W]: -1, [N]: 0, [S]: 0 };

It can be used with: DX[dir]

Justin
  • 945
  • 12
  • 26
1

Just take the same with an object.

const DX = { E: 1, W: -1, N: 0, S: 0 };

// use
value = DX[dir];

For using with numerical values as direction, you need to map the keys to the directions.

//           N     S     E     W
const DX = { 1: 0, 2: 0, 4: 1, 8: -1 };

// use
value = DX[dir];
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Wow, IDK why I never thought of that. Thank you for your answer :) I'll upvote it, however I won't accept just yet to give some time for other approaches to come in, as I want to continue the discussion if possible. That is very clean and very readable. – Justin Mar 08 '20 at 09:48
  • Another variant would be to omit the `N` and `S` keys, and then `DX[dir] ?? 0`. That might also fit to the usecase. – Jonas Wilms Mar 08 '20 at 09:57
  • 1
    `DX = dir => {E: 1, W: -1}[dir] ?? 0` and use as `value = DX(dir)` – Praveen Soni Mar 08 '20 at 10:01
  • @JonasWilms, that separates the values into more (confusing) code. – Nina Scholz Mar 08 '20 at 10:08
  • Actually, this isn't working. It's taking the literal string "E" assigned to 1, as opposed to the value of the variable E (the numerical value) 4. So DX[dir] is returning NaN because 4 doesn't map to anything. – Justin Mar 08 '20 at 10:15
  • @PraveenSoni, your answer actually doesn't run (it says syntax error on ':') because in arrow functions, curly braces '{' are used for multiple statement functions, and you're trying to declare an object with that syntax. – Justin Mar 08 '20 at 10:19
  • @PraveenSoni it would have to be something like: `DX = dir =>{ let tmp={E: 1, W: -1}; return tmp[dir] ?? 0 }` except that still doesn't work due to the problem I have with the code above, where E is treated as a string, not a variable name. – Justin Mar 08 '20 at 10:21
  • Thank you for the edit. I found on SO (https://stackoverflow.com/questions/11508463/javascript-set-object-key-by-variable/11508490#11508490) that you can use square braces to use the variable value instead of the literal, so that would be preferred to yours, however you provided the object solution first and edited accordingly, so I will mark your answer as correct. I'm still open to seeing others post their ideas as well. Thank you for your answer. – Justin Mar 08 '20 at 10:29
  • @Justin, ya i think this will work `DX = dir => ({E: 1, W: -1}[dir] ?? 0)` – Praveen Soni Mar 09 '20 at 04:44
0

I would recommend you create an object which maps the directions to the aliases and use it to return the right alias from the function.

const DX = dir => {
    mapping = { E: 1, W: -1, N: 0, S: 0 };
    return mapping[dir];
}
Chief Oye
  • 26
  • 4
  • Good idea to use an object, and still make it a function similar to how I have above. However, this answer still suffers the same fate as the one by Nina, where the letters are mapped to the strings "E", "W", etc, and not the variables with numeric values (1, 2, 4, 8) – Justin Mar 08 '20 at 10:23