0

I have a string, and I have to insert "div" into the string by using start/end values from an array.

var str = "this is a simple string";

var places = [{
    "start": 0,
    "end": 3
  },
  {
    "start": 9,
    "end": 15
  }];

function insert(places, str) {
  // I tryed different approaches like this:
  str = str.forEach(function(item, index) {
    var start = item.start;
    var end = item.end;
    
    var newStr = '<div>'+str[start] + '</div>' + str.slice(end);
    str = newStr;
  });
  $('.h').html(str);
  // I need to get output str as:
  // "<div>this</div> is a <div>simple</div> string"
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="h"></div>

How can I do it using splice or foreach functions?

Mike
  • 137
  • 3
  • 14

4 Answers4

6

You could use str as array of single letters and apply in a loop over places the wanted tags to the letters. Then join all items together and return the string.

This solution works for random sorted places.

function insert(places, str) {
    return places.reduce(function (r, a) {
        r[a.start] = '<div>' + r[a.start];
        r[a.end] += '</div>';
        return r;
    }, str.split('')).join('');
}

var str = "this is a simple string",
    places = [{ "start": 0, "end": 3 }, { "start": 10, "end": 15 }];

console.log(insert(places, str));

One solution without reduce:

function insert(places, str) {
    var r = str.split('');
    places.forEach(function (a) {
        r[a.start] = '<div>' + r[a.start];
        r[a.end] += '</div>';
    });
    return r.join('');
}

var str = "this is a simple string",
    places = [{ "start": 0, "end": 3 }, { "start": 10, "end": 15 }];

console.log(insert(places, str));

For further reading, you could have a look into this answer, why an array of letters might be faster than string functions: How do I replace a character at a particular index in JavaScript?

Community
  • 1
  • 1
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Elegant solution, @Nina. Using `reduce` in this manner should be much preferred to the brittle, in-place string mutation via `forEach` as in my snippet. – Cam Aug 30 '16 at 14:43
  • I didn't downvoted your answer, but It doesn't work as OP expect. If you look carefully, expected output is `
    this
    is a
    simple
    string`, and not `
    this
    is a
    simple
    string` which your function gives
    –  Aug 30 '16 at 14:45
  • @SoftwareEngineer171 that's b/c the original post had the wrong index for the start of his second `
    ` tag. Nina's code works perfectly well and will output as expected if `places[1].start = 10`. @Nina someone was carpet-bombing negative votes to all answers. Mine received 2 down-votes, as did another poster who deleted his answer.
    – Cam Aug 30 '16 at 14:46
2

Assuming that you want to write 0, 4 and 10, 16 (because string 'this' is of length 4, not 3) it becomes

var str = "this is a simple string";
var places = [{
  "start": 0,
  "end": 4
}, {
  "start": 10,
  "end": 16
}];

function insert(places, str){
    var starts = [], ends = [];

    places.forEach(place => {
        starts.push(place.start);
        ends.push(place.end);
    });

    return str.split('').map((chr, pos) => {
        if(starts.indexOf(pos) != -1) chr = '<div>' + chr;
        if(ends.indexOf(pos) != -1) chr = '</div>' + chr;
        return chr;
    }).join('')
}

console.log(insert(places, str)); // <div>this</div> is a <div>simple</div> string
1

Here's one way of accomplishing your goal, using Array#forEach and successively mutating the string w/ an 11 chars shift for each <div></div> tag added.

var str = "this is a simple string";

// change place into an array of objects
var place = [
  {
    "start": 0,
    "end": 3
  },
  {
    "start": 10,
    "end": 15
  }
];

function insert(place, str) {
  var shift = 0;
  place.forEach(function(p){
    str = str.substring(0,p.start+shift) + "<div>" + 
    str.substring(p.start+shift,p.end+shift+1) + "</div>" + str.substring(p.end+shift+1);
    shift += 11; //shift 11 chars for each match
  });
  return str;
}

console.log( insert(place,str) );

Note this solution depends upon the places array holding indices in ascending order.

Cam
  • 921
  • 7
  • 13
0

You might do as follows... though i would recommend you to chose your string indices better. Especially it would be better if the end index doesn't point the last character but the one beyond. I have amended the data accordingly. We are adding an offset of 11 for every round of the reduce since our string gains "<div></div>" many (11) characters every round.

var str = "this is a simple string";

  place = [{
            "start": 0,
              "end": 4
           },
           {
            "start": 10,
              "end": 16
           }],
 newStr = place.reduce((s,o,i) => s.slice(0,o.start + (i*11)) + "<div>" +
                                  s.slice(o.start + (i*11), o.end + (i*11)) + "</div>" +
                                  s.slice(o.end + (i*11)), str);
console.log(newStr);

Of course it might be generalized to insert any tag.

Redu
  • 25,060
  • 6
  • 56
  • 76