Imp3ll
Imp3ll

Reputation: 41

How to create my own substring method in JS?

Im trying create my own substring method in JS

function substr(string, p1 = 0, p2 = string.length) {
  if (string.length === 0 || p2 < 0 || p1 > p2) return '';
  const p11 = p1 <= 0 ? 0 : p1
  let p22 = p2 > string.length ? string.length : p2
  const str = string.split('').reduce((acc, item, i) => {
    if (i >= p11 && i < p22) {
      console.log('i:', i)
      return acc.concat(item)
    }
    return acc
  }, '');

  console.log('inside', str)
  return str
}

when Im test this code I have an error

expect(substr('abba', 1, 0)).toEqual(''); // pass
expect(substr('abba', 0, 1)).toEqual('a'); // pass
expect(substr('abba', 0, 1)).toEqual('a'); // pass
expect(substr('abba', 1, 2)).toEqual('bb'); // failed

How I can fix my code to pass tests?

Upvotes: 0

Views: 350

Answers (1)

jiwopene
jiwopene

Reputation: 3627

There is your code example:

     1 function substr(string, p1 = 0, p2 = string.length) {
     2    if (string.length === 0 || p2 < 0 || p1 > p2) return '';
     3    const p11 = p1 <= 0 ? 0 : p1
     4    let p22 = p2 > string.length ? string.length : p2
     5    const str = string.split('').reduce((acc, item, i) => {
     6      if (i >= p11 && i < p22) {
     7        console.log('i:', i)
     8        return acc.concat(item)
     9      }
    10      return acc
    11    }, '');
    12
    13    console.log('inside', str)
    14    return str
    15  }

There are multiple mistakes in your code. You are still learning. That's no problem – everyone has started somehow. Let's name the mistakes:

  • On the line 2, there is p1 > p2. That does not make sense. You do not want to return empty string if the distance between string start and the substring start is greater that the maximum substring length.

  • Your variable names do not make sense. Try using names like startpos or length instead of names like p1 or p2.

  • And the third thing I found is that your substring function returns substring between positions p1 and p2, unlike the JS's builtin String.prototype.substr which returns substring between p1 and p1+p2.


Try it this way:

function substr(string, start, length = string.length) {
  let outStr = '';
  for (let pos = start;
       pos < start + length && pos < string.length;
       pos++) {
    outStr += string[pos];
  }
  return outStr;
}

function expect(actual) {
  return {
    'toEqual': function (expected) {
      if (actual == expected) {
        document.body.innerText += `“${actual}” == “${expected}” (pass)\n`;
      } else {
        document.body.innerText += `“${actual}” /= “${expected}” (fail)\n`;
      }
    },
  };
}

expect(substr('abba', 1, 0)).toEqual('');
expect(substr('abba', 0, 1)).toEqual('a');
expect(substr('abba', 0, 1)).toEqual('a');
expect(substr('abba', 1, 2)).toEqual('bb');

I think that using split and reduce for this is overkill. But if you want to use it, there is the code in the “pure functional style”, but it is inefficient, because it needs string.length steps instead of length steps to compute the result.

function substr(string, start, length = string.length) {
  return string
    .split('') // split between every character
    .reduce((head, char, index) =>
      (index >= start && head.length < length) // if we reached the substring start and there “is space” in the substring,
      ? head + char                           // append another character
      : head,                                 // else keep the substring
      ''); // start with empty substring
}

function expect(actual) {
  return {
    'toEqual': function (expected) {
      if (actual == expected) {
        document.body.innerText += `“${actual}” == “${expected}” (pass)\n`;
      } else {
        document.body.innerText += `“${actual}” /= “${expected}” (fail)\n`;
      }
    },
  };
}

expect(substr('abba', 1, 0)).toEqual('');
expect(substr('abba', 0, 1)).toEqual('a');
expect(substr('abba', 0, 1)).toEqual('a');
expect(substr('abba', 1, 2)).toEqual('bb');

You should also have better test cases. Write test cases as if wou would teach someone to use your routines. The test cases can be important for understanding complex code. For example, take you favorite sentence and test the function using it. It will be easier to understand the test case the next time you see the code.

Upvotes: 2

Related Questions