3

So the goal is to fragment an array to subarrays on the stumble of a certain element Example below for array.split("stop here")

["haii", "keep", "these in the same array but", "stop here", "then continue", "until you reach", "another", "stop here", "and finally", "stop here", "stop here"]

that to

[
  ["haii", "keep", "these in the same array but"], ["then continue", "until you reach", "another"], ["and finally"]
]

What I tried till now is not working very well:

Array.prototype.split = function (element) {
  const arrays = [];
  // const length = this.length;
  let arrayWorkingOn = this;
  for(let i=0; i<arrayWorkingOn.length; i++) {
    if(this[i] === element) {
      const left = arrayWorkingOn.slice(0, i);
      const right = arrayWorkingOn.slice(i, arrayWorkingOn.length);
      arrayWorkingOn = right;
      arrays.push(left);
      console.log(right);
    }
  }
  arrays.push(arrayWorkingOn); //which is the last 'right'
  return arrays;
}

Thanks in advance for your time and effort!

4 Answers 4

1

First .join() your arrays with an unique seperator in my case UNIQUE_SEPERATOR

Then you split it up first with .split("stop here") that returns you an array with 3 strings in it.

Now you need to .map() over the array and split it up by your seperator (UNIQUE_SEPERATOR) and .filter() out the "" values.

At the end you filter out the empty arrays by checking its length and you are done.

let arr = [
  "haii",
  "keep",
  "these in the same array but",
  "stop here",
  "then continue",
  "until you reach",
  "another",
  "stop here",
  "and finally",
  "stop here",
  "stop here"
];

Array.prototype.split = function() {
  return this.join("UNIQUE_SEPERATOR")
    .split("stop here")
    .map(el => el.split("UNIQUE_SEPERATOR").filter(Boolean))
    .filter(arr => arr.length);
};

console.log(arr.split());

Sign up to request clarification or add additional context in comments.

Comments

1

This answer is inspired by the answer of ibrahim mahrir.

Array.prototype.split = function (element) {
  const arrays = [];
  const length = this.length;
  let accumulatedArray = [];
  for(let i=0; i<length; i++) {
    if( this[i] === element ) {
      if( accumulatedArray.length > 0 ) arrays.push(accumulatedArray);
      accumulatedArray = [];
    } else {
      accumulatedArray.push(this[i]);
    }
  }
  if( accumulatedArray.length > 0 ) arrays.push(accumulatedArray);;
  return arrays;
}

1 Comment

Guys thanks for all your answers I'll check them out later cause now I got a satisfying answer and I'll continue work with it. Thanks for all the support!
1

If you're going to loop the entire array then don't use slice at all, just accumulate the items as you go in an array and when you encounter the element just push that array and create a new one, like so:

Array.prototype.split = function (element) {
  const arrays = [];

  let currentArray = [];                         // is used to accumulate the sub arrays
  for(let item of this) {                        // for each item of the array
    if(item === element) {                       // if item is the element
      arrays.push(currentArray);                 // add the current accumulated array to arrays
      currentArray = [];                         // and start accumulating a new one
    } else {                                     // otherwise
      currentArray.push(item);                   // add the item to the accumulated array
    }
  }
  arrays.push(currentArray);                     // don't forget the last one

  return arrays;
}

Note: This answer uses the correct behavior of split which is not what the question asks. There should be empty arrays in the resulting array if the elements you want to split on are the first item, the last item or adjacent items in the original array. 'abcbdb'.split('b') should result in ['a', 'c', 'd', ''] not ['a', 'c', 'd']. If you want to ignore the empty arrays, check out Jhon's accepted answer above.

Demo:

Array.prototype.split = function (element) {
  const arrays = [];

  let currentArray = [];
  for(let item of this) {
    if(item === element) {
      arrays.push(currentArray);
      currentArray = [];
    } else {
      currentArray.push(item);
    }
  }
  arrays.push(currentArray);

  return arrays;
}


let result = ["haii", "keep", "these in the same array but", "stop here", "then continue", "until you reach", "another", "stop here", "and finally", "stop here", "stop here"].split("stop here");

console.log(result);

2 Comments

Your answer was the most simple but I went on to update it for dealing with all cases (that I tested) in my answer. Please if I made some performance hitches correct me. (maybe by doing another traversal throught the final array for removing empty arrays instead of checking on each iteration inside the same traversal)
Yeah, your answer is perfect for your use case. I forgot about pushing the last accumulated array, thanks for pointing that out. I'll keep mine as is it is because that's the correct behavior of split and that may help future users, and you should accept your own answer because it fits better with your question.
0

A few thoughts:

  1. Rewritting prototypes is an advanced idea, and probably unecessary.

  2. Look into utility librairies such as lodash for utility functions such as this one.

  3. If you want to do it manually anyway, I'd try:

    array.join("/$/").split("stop here").map(part => part.split("/$/").filter(Boolean))

That first convert your array to a string that has a split methods and back to an array again.

Demo:

const array = ["haii", "keep", "these in the same array but", "stop here", "then continue", "until you reach", "another", "stop here", "and finally", "stop here", "stop here"]
console.log(array.join("/$/").split("stop here").map(part => part.split("/$/").filter(Boolean)))

2 Comments

the .join("/") assumes the string don't have a / in them already. That will fail on an array like ["name/last name", "stop here", "age"]
That's won't fix it any marker could be part of a string

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.