Вставте рядок у певному індексі


333

Як я можу вставити рядок у конкретний індекс іншої рядки?

 var txt1 = "foo baz"

Припустимо, я хочу вставити "бар" після "foo", як я можу цього досягти?

Я подумав substring(), але повинен бути більш простий шлях вперед.


Відповіді:


257

Ви можете прототипувати свій власний текст splice()у String.

Поліфіл

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"


EDIT: Змінено його, щоб забезпечити 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)). Це також трохи коротше, бо мало того, що варто.
Tim Down

8
Чи пропонує ES6 кращу альтернативу? Можна принаймні використовувати строкову інтерполяцію, як-от`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Джей

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.
Містер-ІДЕ

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; текст = {}; текст [a] = "xx"; текст [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, вам не потрібно буде використовувати жодних селекторів запитів або оновлювати InternalText. Зміни відображатимуться через його обов'язковість.

Якщо вам знадобилася рядок, просто перейдіть до властивості текстового вмісту вузла.

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 означає?
Енріке Бермудес

Btw, спасибі за другий метод. Це працює як шарм!
Енріке Бермудес

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);

Очевидно, це була б фарба, яку потрібно використовувати, тому що ви повинні кожен раз подавати функцію у свою функцію, але на даний момент я не знаю, як перетворити її на щось легше, як 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

Ви можете легко зробити це за допомогою regexp в одному рядку коду

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. Знову постригайте за допомогою 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.