DEV Community is a community of 796,806 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Critique my JS solution to this CodeWars Kata

The Kata

The exercice basically asks to convert any 'T' to 'A' any 'C' to 'G' and vice versa for any given string.

My solution

I know it might not be the exemplary solution but it was the first thing that popped in my head.
I wrote it first like this:

function DNAStrand(dna){
let map = Array.prototype.map;
let reversedDna = map.call(dna, function(x) {
let y;
switch(x){
case 'A': y = 'T'; break;
case 'T': y = 'A'; break;
case 'G': y = 'C'; break;
case 'C': y = 'G'; break;
}
return y;
});
return reversedDna.join('');
}

then I thought to myself: "I can remove that y variable." So I did:

function DNAStrand(dna){
let map = Array.prototype.map;
let reversedDna = map.call(dna, function(x) {
let y;
switch(x){
case 'A': return 'T'; break;
case 'T': return 'A'; break;
case 'G': return 'C'; break;
case 'C': return 'G'; break;
}
});
return reversedDna.join('');
}

Then I thought: "I can get rid of the break lines since the return statements are already breaking, can't I?"

function DNAStrand(dna){
let map = Array.prototype.map;
let reversedDna = map.call(dna, function(x) {
let y;
switch(x){
case 'A': return 'T';
case 'T': return 'A';
case 'G': return 'C';
case 'C': return 'G';
}

});
return reversedDna.join('');
}

Is there any way to improve my solution? Do you have another way of doing that? Leave your remarks in the comments

Discussion (9) Dian Fay
const lookup = {
'A': 'T',
'T': 'A',
'G': 'C',
'C': 'G'
};

function DNAStrand(dna) {
return [...dna].reduce((reversed, nucleotide) => {
return reversed + lookup[nucleotide];
}, '');
}

Defaulting to const declarations helps keep track of what's allowed to change. reduce is more appropriate when you need to accumulate results than the two-step of generating a new array and joining it. The hashtable lookup keeps the reducer body as short as possible, but there's nothing wrong with a switch per se. Donald Merand • Edited on

@dmfay This is a very elegant solution! I like that you're explaining the reasons why you did things like use a const etc.

One thing you didn't mention is the use of the spread syntax ([...dna]), which is definitely handy in JS when passing arrays around. Maurice Hayward

wow I didn't know

[ ...dna]

would automatically turn your string into an array. I always use

dna.spilt("")

I'm gonna change my solution to reflect this newfound knowledge. Isaac Lyman

Came to the comments to post this exact solution. Very elegantly done. Meghan (she/her)
function DNAStrand(dna) {
return dna.split('').reduce((ac,cv) => {
switch(cv) {
case 'A': return ac+'T';
case 'T': return ac+'A';
case 'G': return ac+'C';
case 'C': return ac+'G';
default:  return ac+cv;
}
}, '');
} Salim MAHBOUBI • Edited on

Thanks Sean ! I don't know why I didn't think of reduce... Maurice Hayward • Edited on

I see no problem with your solution. I like how you iteratively improved your solution.

Here is my solution.

var complements = { A: 'T', T:'A', C: 'G', G: 'C'}

function DNAStrand(dna){
var dnaArray = [...dna]; //turns string into arrary , where each character is an element

var complementArray = dnaArray.map(x => complements[x]) //maps each character with it's complement and puts the result in an array

return complementArray.join("") //turn array into a string

}

or in one line

var complements = { A: 'T', T:'A', C: 'G', G: 'C'}

function DNAStrand(dna){
return  [...dna].map(x => complements[x]).join("")
} Salim MAHBOUBI

Nice and clean. Thanks Maurice!