JavaScript Divide Array

I am currently tackling the challenge of creating a custom string splitter function, and I must say, it's proving to be more complex than anticipated.

Essentially, the function takes in a string and an array of delimiter values that the string will be split on. It then returns an array of substrings, eliminating any empty ones and including the delimiters themselves. In cases where the same point in the string can be split by two different values, the longer one takes precedence.

For example:

split("Go ye away, I want some peace && quiet. & Thanks.", ["Go ", ",", "&&", "&", "."]);

The expected output would be:

["Go ", "ye away", ",", " I want some peace ", "&&", " quiet", ".", " ", "&", " Thanks", "."]

Do you have any ideas for a straightforward algorithm to achieve this? While I doubt there is a built-in JavaScript method for this specific task, it would certainly make things easier if there were.

Answer №1

Is something similar to this what you had in mind?

function customSplit(input, delimiters) {

    // Arrange delimiters array by length to prevent confusion
    delimiters.sort(function(a, b) {
       if (a.length > b.length) { return -1; }
       return 0;
    }

    var output = [];

    // Analyze input character by character
    for (var i = 0; i < input.length; i++) {
        for (var j = 0; j < delimiters.length; j++) {
            if (input.substr(i, delimiters[j].length) == delimiters[j]) {

                // Append first portion of input to result
                if (i > 0) {
                    output.push(input.substr(0, i));
                }
                output.push(delimiters[j]);

                // Reset input and loop
                input = input.substr(i + delimiters[j].length);
                i = 0;
                j = 0;
            }
        }
    }

    return output;
}

var userInput      = "Go ye away, I want some peace && quiet. & Thanks.";
var delimiterList = ["Go ", ",", "&&", "&", "."];

console.log(customSplit(userInput, delimiterList));
// Result: ["Go ", "ye away", ",", " I want some peace ",
//          "&&", " quiet", ".", " ", "&", " Thanks", "."]

Answer №2

Looking for an accurate solution:

function megasplit(toSplit, splitters) {
    var splitters = splitters.sorted(function(a,b) {return b.length-a.length});
                                                          // sort by length; added here for better readability, easy to separate rest of function into helper function
    if (!splitters.length)
        return toSplit;
    else {
        var token = splitters[0];
        return toSplit
            .split(token)             // split on token
            .map(function(segment) {  // call recursively on segments
                 return megasplit(segment, splitters.slice(1))
             })
            .intersperse(token)       // re-insert token
            .flatten()                // concatenate segments
            .filter(Boolean);
    }
}

Demonstration:

> megasplit(
      "Go ye away, I want some peace && quiet. & Thanks.",
      ["Go ", ",", "&&", "&", "."]
  )
["Go ", "ye away", ",", " I want some peace ", "&", "&", " quiet", ".", " ", "&", " Thanks", "."]

Reusable Machinery:

Array.prototype.copy = function() {
    return this.slice()
}
Array.prototype.sorted = function() {
    var copy = this.copy();
    copy.sort.apply(copy, arguments);
    return copy;
}
Array.prototype.flatten = function() {
    return [].concat.apply([], this)
}
Array.prototype.mapFlatten = function() {
    return this.map.apply(this,arguments).flatten()
}
Array.prototype.intersperse = function(token) {
    // [1,2,3].intersperse('x') -> [1,'x',2,'x',3]
    return this.mapFlatten(function(x){return [token,x]}).slice(1)
}

Important Notes:

  • This task required considerable research to accomplish elegantly:
    • (Deep) copying an array using jQuery
    • What is the most efficient way to concatenate N arrays in JavaScript? (developed my own method)
    • How can I split text on commas not within double quotes, while keeping the quotes? (created my own method)
  • The complexity increased as tokens were required to remain intact within the string and not be split (resulting in "&", "&"). This necessitated recursion over using reduce.
  • My personal preference would include empty strings with splits. While avoiding recursive splitting on the tokens, I would simplify the function to make the output mimic a standard .split like
    ["", "Go ", "ye away", ",", " I want some peace ", "&&", " quiet", ".", " ", "&", " Thanks", ".", ""]
  • It is worth noting that, if there's flexibility in requirements, the code could be condensed from a 15/20-liner to a 1/3-liner:

1-line solution following canonical splitting behavior:

Array.prototype.mapFlatten = function() {
    ...
}
function megasplit(toSplit, splitters) {
    return splitters.sorted(...).reduce(function(strings, token) {
        return strings.mapFlatten(function(s){return s.split(token)});
    }, [toSplit]);
}

3-line solution for readability:

Array.prototype.mapFlatten = function() {
    ...
}
function megasplit(toSplit, splitters) {
    var strings = [toSplit];
    splitters.sorted(...).forEach(function(token) {
        strings = strings.mapFlatten(function(s){return s.split(token)});
    });
    return strings;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for passing multiple parameters to Web API controller methods in Angular 4

Want to learn how to use Spring Rest Api: @RequestMapping(value={"/save-userlist"}, method=RequestMethod.POST) public ResponseEntity<?> saveUserList(@RequestBody UserListDTO userListDTO, @RequestBody List<User> users, @RequestParam Integer ...

Removing the empty option in a select element with ng-model

There's a situation I'm dealing with that involves a select dropdown along with a refresh button and a plus button. The issue arises when clicking the refresh button sets the model to null, while clicking the plus button displays the dropdown wit ...

What could be causing the console.log to not work in this Express code snippet?

I'm currently utilizing PouchDB in conjunction with Express for retrieving documents from a database: server.js: var express = require('express') var PouchDB = require('pouchdb') var app = express() var db = new PouchDB('vu ...

Switch up the language on your website in real-time with the power of

I am currently working on a project that requires support for different languages in the GUI (Spanish, English, German, etc). Thanks to CodeIgniter, I am able to easily implement language support for PHP views using the Language Class. I can load pre-defin ...

Creating a TypeScript class to extend the JavaScript object prototype

tl;dr: My goal is to apply compiled Typescript prototype definitions to objects I have defined as classes. Situation: I am looking to enhance a JavaScript object with business logic specified in a typescript class. For example: class Address { constr ...

Tips on duplicating objects in TypeScript with type annotations

My goal is to inherit properties from another object: interface IAlice { foo: string; bar: string; }; interface IBob extends IAlice { aFunction(): number; anotherValue: number; }; let alice: IAlice = { foo: 'hi', bar: 'bye&apo ...

Getting an invalid ELF header error when using nodejs iconv

Just checking on my local computer (mac terminal, with node web.js) I confirmed that it is running on the local server. However, every time I try to deploy it to the server, I keep getting this error message: Error: /home/hosting_users//apps//node_modul ...

Using list values as dictionary indices in Z3py: A Comprehensive Guide

I am working with a Python array (Arr) containing j integer elements, a Z3 list (X) consisting of z3 Int variables, and a Z3 dictionary (D) containing Z3 Bool variables. For example: X = [ [ x_0_0, x_0_1, …, x_0_j], [ x_1_0, x_1_1, ...

Launching in an Angular reactive form

When working with Angular reactive forms, I am facing an issue where I want to set a form control value using a property from a service. However, upon submitting the form, the value of the form control does not reflect the expected property value from the ...

The validation process fails when the button is clicked for the second time

When adding a username and email to the userlist, I am able to validate the email on initial page load. However, if I try to enter an invalid email for the second time and click the add button, it does not work. <form id="myform"> <h2>Ad ...

Facing difficulties in resetting the time for a countdown in React

I've implemented the react-countdown library to create a timer, but I'm facing an issue with resetting the timer once it reaches zero. The timer should restart again and continue running. Take a look at my code: export default function App() { ...

Discovering the art of importing JavaScript files dynamically within controllers

I have one main form through which I pass data from 10 different components, each including the ID of a table that I need to retrieve data from in the database. The issue I am facing is that the code responsible for fetching this data asynchronously is spr ...

Symmetric Matrix Implementation in Java for Vehicle Routing Problem

I am currently working on a project related to vehicle routing problems, specifically focusing on generating a problem instance. For example, consider a scenario where there is a Depot "0" and Three Stations "1","2" and "3". To start, I have set up the ...

What is the best way to extract the date January 1, 1970 from a datepicker?

Currently, I am utilizing a datepicker along with a function that converts dates from dd-mm-yyyy to yyyy-mm-dd format. The dates in the database are stored in yyyy-mm-dd format, so I need to first convert them to dd-mm-yyyy for better readability. When sub ...

Exploring the differences between detecting the XMLHttpRequest object in JavaScript and using the try

When it comes to determining browser support for AJAX, I typically rely on object detection like this: if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } ...

JavaScript form button press tracker

Hello! I've been tackling a challenge involving a JavaScript function to count button clicks. The catch is, the button type is set to submit, causing the page to reload every time I click it. Below is the snippet of code that contains the problemati ...

Generate a dynamic animation by combining two images using jQuery

My attempt to animate two images is not working. I received some help on Stack Overflow but still facing issues with my CSS and HTML code. This is the code I am using: $(document).ready(function() { $(".animar").click(function() { $("#img4" ...

Trouble with sending data from jQuery Ajax to Node.js server

I am in the process of developing a video streaming platform that needs to constantly update the backend on the status of the videos being played. However, I am encountering an issue where the data sent through an ajax request appears as an empty object {} ...

Is it feasible to customize the appearance of native scrollbars in GWT without the need for custom scrollbar definitions or the use of ScrollPanel or CustomScrollPanel?

After encountering an issue with a page jumping due to the appearance of a vertical scroll bar, I have decided to always display the scroll bar by applying html { overflow-y: scroll !important; }, instead of using a script to monitor and adjust window/docu ...

Retrieve the current time of day based on the user's timezone

Currently, I am working with a firebase cloud function that is responsible for sending push notifications to my app. My main requirement is to send notifications only during the day time. To achieve this, I have integrated moment-timezone library into my p ...