Вставить строку по определенному индексу


334

Как я могу вставить строку по определенному индексу другой строки?

 var txt1 = "foo baz"

Предположим, я хочу вставить «bar» после «foo», как мне этого добиться?

Я подумал substring(), но должен быть более простой и прямой путь.


Ответы:


257

Вы можете создать свой собственный splice()в String.

Polyfill

if (!String.prototype.splice) {
    /**
     * {JSDoc}
     *
     * The splice() method changes the content of a string by removing a range of
     * characters and/or adding new characters.
     *
     * @this {String}
     * @param {number} start Index at which to start changing the string.
     * @param {number} delCount An integer indicating the number of old chars to remove.
     * @param {string} newSubStr The String that is spliced in.
     * @return {string} A new string with the spliced substring.
     */
    String.prototype.splice = function(start, delCount, newSubStr) {
        return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
    };
}

пример

String.prototype.splice = function(idx, rem, str) {
    return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};

var result = "foo baz".splice(4, 0, "bar ");

document.body.innerHTML = result; // "foo bar baz"


РЕДАКТИРОВАТЬ: изменил его, чтобы убедиться, что remэто абсолютное значение.


6
Я знаю, что это с 2010 года, но приведенное ниже sliceрешение лучше и проще. (Сплайсинг деструктивен, срез - нет, и лучше избегать изменения «объектов, которые вы не знаете»). Это решение не должно быть первым видимым ответом, даже если оно имело смысл в то время.
Эйрик Биркеланд

6
@EirikBirkeland: Строки неизменны. Приведенный выше код не изменяет никакой объект. В любом случае, ваше представление о том, чтобы не изменять «объекты, которые вы не знаете », исключает методы мутации в массиве. Ты говоришь, что предпочитаешь делать my_array[my_array.length] = itemвместо my_array.push(item)?

4
Извините, я имел в виду "объекты, которые вы не СОБСТВЕННЫЕ". Вы правы spliceв этом деле; действительно, строки неизменны. По этой причине я думаю, что spliceвыбор плохого ключевого слова все же. Мое главное возражение против произвольного расширения прототипов, если они не являются стандартными полифиллами.
Эйрик Биркеланд,

1
Это невероятно плохая практика - модифицировать встроенные объекты. Как мы видели в SmooshGate , это рискует нарушить ваш код, поскольку в язык добавлены новые функциональные возможности, и, если ваши безответственные изменения каким-либо образом попадут в библиотеку, которая увидит значительное распространение в Интернете, это может заблокировать использование простого и понятного имени метода. для новой функциональности.
Шон

401

Вставка по определенному индексу (а не, скажем, по первому пробелу) должна использовать срез строки / подстроку:

var txt2 = txt1.slice(0, 3) + "bar" + txt1.slice(3);

4
@AlejandroSalamancaMazuelo: substringбыло бы хорошо здесь. Я предпочитаю sliceв целом, потому что он более гибкий (например, отрицательные показатели "foo baz".slice(1, -2)). Это также немного короче, для немногого, что стоит.
Тим Даун

8
ES6 предлагает лучшую альтернативу? Можно хотя бы использовать интерполяцию строк, как`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Jay

1
Это не использует deleteфункцию, как указано выше; топ ответ ...
Мистер Полихирл

11
@ Mr.Polywhirl: Нет. Вопрос не упоминает о необходимости сделать это.
Тим Даун

133

Вот метод, который я написал, который ведет себя как все другие языки программирования:

String.prototype.insert = function(index, string) {
  if (index > 0)
  {
    return this.substring(0, index) + string + this.substring(index, this.length);
  }

  return string + this;
};

//Example of use:
var something = "How you?";
something = something.insert(3, " are");
console.log(something)

Ссылка:


1
Возможно, вам понадобится добавить фигурные скобки {}в блоки if-else.
Mr-IDE,

3
Нет, не нужно. Но elseэто избыточно.
Bitterblue

72

Просто сделайте следующую функцию:

function insert(str, index, value) {
    return str.substr(0, index) + value + str.substr(index);
}

и затем используйте это так:

alert(insert("foo baz", 4, "bar "));

Вывод: foo bar baz

Он ведет себя точно так же, как C # (Sharp) String.Insert (int startIndex, строковое значение).

ПРИМЕЧАНИЕ. Эта функция вставки вставляет строковое значение (третий параметр) перед указанным целочисленным индексом (вторым параметром) в строку str (первый параметр), а затем возвращает новую строку без изменения str !


16

ОБНОВЛЕНИЕ 2016: Вот еще одна забавная (но более серьезная!) Функция-прототип, основанная на однострочном RegExpподходе (с предварительной поддержкой undefinedили отрицательной index):

/**
 * Insert `what` to string at position `index`.
 */
String.prototype.insert = function(what, index) {
    return index > 0
        ? this.replace(new RegExp('.{' + index + '}'), '$&' + what)
        : what + this;
};

console.log( 'foo baz'.insert('bar ', 4) );  // "foo bar baz"
console.log( 'foo baz'.insert('bar ')    );  // "bar foo baz"

Предыдущее (до 2012 года) решение для развлечения :

var index = 4,
    what  = 'bar ';

'foo baz'.replace(/./g, function(v, i) {
    return i === index - 1 ? v + what : v;
});  // "foo bar baz"

1
Это также хорошо, если вам нужно вставить текст с несколькими индексами в строку. Смотрите мой ответ ниже, если это так.
Джейк Стоффлер

12

Если кто-то ищет способ вставить текст с несколькими индексами в строку, попробуйте это:

String.prototype.insertTextAtIndices = function(text) {
    return this.replace(/./g, function(character, index) {
        return text[index] ? text[index] + character : character;
    });
};

Например, вы можете использовать это для вставки <span>тегов с определенными смещениями в строку:

var text = {
    6: "<span>",
    11: "</span>"
};

"Hello world!".insertTextAtIndices(text); // returns "Hello <span>world</span>!"

1
Я попробовал этот метод, но заменил «6» и «11» переменными, которые не работают - что я делаю неправильно - помогите, пожалуйста. Заранее спасибо :)
Декс Дейв

1
6 и 11 - индексы, по которым текст будет вставлен в строку. 6: "<span>"говорит: в индексе 6 вставьте текст "<span>". Вы говорите, что хотите использовать значение целочисленной переменной в качестве индекса вставки? Если это так, попробуйте что-то вродеvar a=6, text = {}; text[a] = "<span>";
Джейк Стоффлер

1
да, я хочу использовать целочисленные переменные в качестве вставки, ваш метод работал - спасибо вам - это то, что я использовал var a = 6; var b = 11; текст = {}; text [a] = "xx"; text [b] = "yy"; - есть ли лучший способ написать это, хотя
Декс Дейв

11

Это в основном то, что делает @ Bass33, за исключением того, что я также даю возможность использовать отрицательный индекс для подсчета с конца. Вроде как метод substr позволяет.

// use a negative index to insert relative to the end of the string.

String.prototype.insert = function (index, string) {
  var ind = index < 0 ? this.length + index  :  index;
  return  this.substring(0, ind) + string + this.substring(ind, this.length);
};

Вариант использования: Допустим, у вас есть полноразмерные изображения с использованием соглашения об именах, но вы не можете обновить данные, чтобы также предоставить URL-адреса миниатюр.

var url = '/images/myimage.jpg';
var thumb = url.insert(-4, '_thm');

//    result:  '/images/myimage_thm.jpg'

9

Учитывая ваш текущий пример, вы можете достичь результата либо

var txt2 = txt1.split(' ').join(' bar ')

или

var txt2 = txt1.replace(' ', ' bar ');

но, учитывая, что вы можете делать такие предположения, вы можете также перейти непосредственно к примеру Гуллена.

В ситуации, когда вы действительно не можете делать никаких предположений, кроме символьного индекса, тогда я действительно выбрал бы решение для подстроки.



6

Я знаю, что это старая тема, но здесь действительно эффективный подход.

var tn = document.createTextNode("I am just  to help")
t.insertData(10, "trying");

Что в этом хорошего, так это то, что он принуждает содержимое узла. Поэтому, если бы этот узел уже был в DOM, вам не нужно было бы использовать какие-либо селекторы запросов или обновлять innerText. Изменения будут отражены из-за его обязательности.

Если вам нужна строка, просто получите доступ к свойству текстового содержимого узла.

tn.textContent
#=> "I am just trying to help"

6

Ну, мы можем использовать метод подстроки и слайса.

String.prototype.customSplice = function (index, absIndex, string) {
    return this.slice(0, index) + string+ this.slice(index + Math.abs(absIndex));
};


String.prototype.replaceString = function (index, string) {
    if (index > 0)
        return this.substring(0, index) + string + this.substring(index, this.length);

    return string + this;
};


console.log('Hello Developers'.customSplice(6,0,'Stack ')) // Hello Stack Developers
console.log('Hello Developers'.replaceString(6,'Stack ')) //// Hello Stack Developers

Единственная проблема метода подстроки заключается в том, что он не будет работать с отрицательным индексом. Он всегда берет строковый индекс с 0-й позиции.


Для чего нужен absIndex?
Энрике Бермудес

Кстати, спасибо за второй способ. Работает как часы!
Энрике Бермудес

5
function insertString(string, insertion, place) {
  return string.replace(string[place] + string[place + 1], string[place] + insertion + string[place + 1])
}

Так что для вас это было бы insertString("foo baz", "bar", 3);

Очевидно, что это было бы краской для использования, потому что вы должны каждый раз вводить свою строку для функции, но в настоящий момент я не знаю, как превратить ее в нечто более простое, например a string.replace(insertion, place). Идея все еще стоит, хотя.


4

Вы можете использовать регулярные выражения с динамическим шаблоном.

var text = "something";
var output = "                    ";
var pattern = new RegExp("^\\s{"+text.length+"}");
var output.replace(pattern,text);

выходы:

"something      "

Это заменяет text.lengthпробельные символы в начале строки output. В RegExpсредства ^\- начиная от линии \sлюбого белого символа пробела, повторяющиеся {n}разы, в этом случае text.length. Используется \\для \избежания обратной косой черты при построении шаблонов такого типа из строк.


3

другое решение, разрезать строку на 2 и положить строку между ними.

var str = jQuery('#selector').text();

var strlength = str.length;

strf = str.substr(0 , strlength - 5);
strb = str.substr(strlength - 5 , 5);

jQuery('#selector').html(strf + 'inserted' + strb);

3

Вы можете сделать это легко с помощью регулярного выражения в одной строке кода

const str = 'Hello RegExp!';
const index = 6;
const insert = 'Lovely ';
    
//'Hello RegExp!'.replace(/^(.{6})(.)/, `$1Lovely $2`);
const res = str.replace(new RegExp(`^(.{${index}})(.)`), `$1${insert}$2`);
    
console.log(res);

"Привет, Прекрасный RegExp!"


2

Используя ломтик

Вы можете использовать slice(0,index) + str + slice(index). Или вы можете создать метод для этого.

String.prototype.insertAt = function(index,str){
  return this.slice(0,index) + str + this.slice(index)
}
console.log("foo bar".insertAt(4,'baz ')) //foo baz bar

Метод сращивания для строк

Вы можете split()основную строку и добавить затем использовать обычныйsplice()

String.prototype.splice = function(index,del,...newStrs){
  let str = this.split('');
  str.splice(index,del,newStrs.join('') || '');
  return str.join('');
}


 var txt1 = "foo baz"

//inserting single string.
console.log(txt1.splice(4,0,"bar ")); //foo bar baz


//inserting multiple strings
console.log(txt1.splice(4,0,"bar ","bar2 ")); //foo bar bar2 baz


//removing letters
console.log(txt1.splice(1,2)) //f baz


//remving and inseting atm
console.log(txt1.splice(1,2," bar")) //f bar baz

Применение splice () для нескольких индексов

Метод принимает массив массивов каждый элемент массива, представляющий один splice().

String.prototype.splice = function(index,del,...newStrs){
  let str = this.split('');
  str.splice(index,del,newStrs.join('') || '');
  return str.join('');
}


String.prototype.mulSplice = function(arr){
  str = this
  let dif = 0;
  
  arr.forEach(x => {
    x[2] === x[2] || [];
    x[1] === x[1] || 0;
    str = str.splice(x[0] + dif,x[1],...x[2]);
    dif += x[2].join('').length - x[1];
  })
  return str;
}

let txt = "foo bar baz"

//Replacing the 'foo' and 'bar' with 'something1' ,'another'
console.log(txt.splice(0,3,'something'))
console.log(txt.mulSplice(
[
[0,3,["something1"]],
[4,3,["another"]]
]

))


1

Я хотел сравнить метод с использованием подстроки и метод с использованием среза из Base33 и user113716 соответственно, для этого я написал некоторый код

также посмотрите на это сравнение производительности, подстрока, срез

Код, который я использовал, создает огромные строки и вставляет строку "bar" несколько раз в огромную строку

if (!String.prototype.splice) {
    /**
     * {JSDoc}
     *
     * The splice() method changes the content of a string by removing a range of
     * characters and/or adding new characters.
     *
     * @this {String}
     * @param {number} start Index at which to start changing the string.
     * @param {number} delCount An integer indicating the number of old chars to remove.
     * @param {string} newSubStr The String that is spliced in.
     * @return {string} A new string with the spliced substring.
     */
    String.prototype.splice = function (start, delCount, newSubStr) {
        return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
    };
}

String.prototype.splice = function (idx, rem, str) {
    return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};


String.prototype.insert = function (index, string) {
    if (index > 0)
        return this.substring(0, index) + string + this.substring(index, this.length);

    return string + this;
};


function createString(size) {
    var s = ""
    for (var i = 0; i < size; i++) {
        s += "Some String "
    }
    return s
}


function testSubStringPerformance(str, times) {
    for (var i = 0; i < times; i++)
        str.insert(4, "bar ")
}

function testSpliceStringPerformance(str, times) {
    for (var i = 0; i < times; i++)
        str.splice(4, 0, "bar ")
}


function doTests(repeatMax, sSizeMax) {
    n = 1000
    sSize = 1000
    for (var i = 1; i <= repeatMax; i++) {
        var repeatTimes = n * (10 * i)
        for (var j = 1; j <= sSizeMax; j++) {
            var actualStringSize = sSize *  (10 * j)
            var s1 = createString(actualStringSize)
            var s2 = createString(actualStringSize)
            var start = performance.now()
            testSubStringPerformance(s1, repeatTimes)
            var end = performance.now()
            var subStrPerf = end - start

            start = performance.now()
            testSpliceStringPerformance(s2, repeatTimes)
            end = performance.now()
            var splicePerf = end - start

            console.log(
                "string size           =", "Some String ".length * actualStringSize, "\n",
                "repeat count          = ", repeatTimes, "\n",
                "splice performance    = ", splicePerf, "\n",
                "substring performance = ", subStrPerf, "\n",
                "difference = ", splicePerf - subStrPerf  // + = splice is faster, - = subStr is faster
                )

        }
    }
}

doTests(1, 100)

Общее различие в производительности в лучшем случае незначительно, и оба метода работают нормально (даже для строк длиной ~ ~ 12000000)


0
  1. Создание массива из строки
  2. Использовать массив # сплайс
  3. Stringify снова, используя Array # join

Преимущества этого подхода двояки:

  1. просто
  2. Соответствует кодовой точке Unicode

const pair = Array.from('USDGBP')
pair.splice(3, 0, '/')
console.log(pair.join(''))

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.