Wstawianie łańcucha w pozycji x innego łańcucha

237

Mam dwie zmienne i muszę wstawić ciąg bdo ciągu aw punkcie reprezentowanym przez position. Wynik, którego szukam to „Chcę jabłka”. Jak mogę to zrobić za pomocą JavaScript?

var a = 'I want apple';
var b = ' an';
var position = 6;
Sami
źródło

Odpowiedzi:

376

var a = "I want apple";
var b = " an";
var position = 6;
var output = [a.slice(0, position), b, a.slice(position)].join('');
console.log(output);


Opcjonalnie: Jako prototypowa metoda String

Poniższych można użyć do podziału textna inny ciąg w żądanym index, z opcjonalnym removeCountparametrem.

if (String.prototype.splice === undefined) {
  /**
   * Splices text within a string.
   * @param {int} offset The position to insert the text at (before)
   * @param {string} text The text to insert
   * @param {int} [removeCount=0] An optional number of characters to overwrite
   * @returns {string} A modified string containing the spliced text.
   */
  String.prototype.splice = function(offset, text, removeCount=0) {
    let calculatedOffset = offset < 0 ? this.length + offset : offset;
    return this.substring(0, calculatedOffset) +
      text + this.substring(calculatedOffset + removeCount);
  };
}

let originalText = "I want apple";

// Positive offset
console.log(originalText.splice(6, " an"));
// Negative index
console.log(originalText.splice(-5, "an "));
// Chaining
console.log(originalText.splice(6, " an").splice(2, "need", 4).splice(0, "You", 1));
.as-console-wrapper { top: 0; max-height: 100% !important; }

jAndy
źródło
3
W przypadku długich ciągów to rozwiązanie jest szybsze (ponieważ kopiuje mniej) niż rozwiązanie Nickfa.
pkt.
35
To rozwiązanie nie jest szybsze. Byłem ciekawy tego i uruchomiłem jsperf. To uwaga dla każdego, kto przeczyta to w przyszłości. jsperf.com/javascript-string-splice . Testowane w najnowszym FF / Chrome / IE10 / IE9. Wykorzystałbym podejście lean nickf w stosunku do tego, zarówno dla przejrzystości, jak i wydajności.
junkyspace,
3
Cóż, to bardzo możliwe. Odpowiedź tutaj ma prawie 3 lata, większość przeglądarek i wersji była wtedy znacznie szybsza dzięki złączeniu Array (szczególnie IE).
jAndy,
1
Proszę o wybaczenie, że ożywiło tak stare pytanie, ale za to, co jestem wart, powinno być var output = [a.slice(0, position + 1), b, a.slice(position)].join('');nadanie OP „Chcę jabłka”, zamiast „Chcę jabłka”.
paulvs,
13
@PaulVon To nigdy nie jest złe, aby coś poprawić, więc nie ma potrzeby wybaczania. W każdym razie trochę się nie zgadzam. Funkcjonalnie robi to, co jest zamierzone, wstawiając łańcuch w pewnej pozycji w innym łańcuchu. W rzeczywistości wstawiony ciąg powinien być jak „an”, co w tym przypadku byłoby bardziej poprawne.
jAndy
262
var output = a.substring(0, position) + b + a.substring(position);

Edycja: zastąpiona .substrprzez .substringponieważ .substrjest teraz starszą funkcją (na https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr )

pseudonim
źródło
47
Według @junkyspace jsperf.com/javascript-string-splice , ta odpowiedź jest 640 razy szybsza niż jAndy.
Paulo Coghi - Przywróć Monikę
5
String.prototype.substrjest już przestarzałe. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Tivie
2
substring w tym przypadku jest bezpośrednim zamiennikiem dla przestarzała substr, więc odpowiedź będzie: var output = a.substring(0, position) + b + a.substring(position);.
Seafish
To nie jest przestarzałe, ale starsze, więc dobrym pomysłem jest zastąpienie go, ponieważ prawdopodobnie stanie się przestarzałe, i zaleca MDN do użycia.substring
froggomad
32

Możesz dodać tę funkcję do klasy string

String.prototype.insert_at=function(index, string)
{   
  return this.substr(0, index) + string + this.substr(index);
}

abyś mógł użyć go na dowolnym obiekcie łańcuchowym:

var my_string = "abcd";
my_string.insertAt(1, "XX");
jasin_89
źródło
3
Złą praktyką jest modyfikowanie natywnego prototypu obiektu: stackoverflow.com/questions/14034180/…
jhujhul 15'18
10

Korzystanie z literałów łańcuchowych ES6 byłoby znacznie krótsze:

const insertAt = (str, sub, pos) => `${str.slice(0, pos)}${sub}${str.slice(pos)}`;
    
console.log(insertAt('I want apple', ' an', 6)) // logs 'I want an apple'

Stefan J
źródło
9

Może nawet lepiej, jeśli określisz pozycję za pomocą indexOf () w następujący sposób:

function insertString(a, b, at)
{
    var position = a.indexOf(at); 

    if (position !== -1)
    {
        return a.substr(0, position) + b + a.substr(position);    
    }  

    return "substring not found";
}

następnie wywołaj funkcję w następujący sposób:

insertString("I want apple", "an ", "apple");

Zauważ, że wstawiam spację po „an” w wywołaniu funkcji, a nie w instrukcji return.

paulo62
źródło
2
Nie o to pytano. Nawet gdyby tak było, nie działałoby to, jeśli wystąpiłoby wiele wystąpień podłańcucha „at”
elachell,
6

Underscore.String biblioteka posiada funkcję, która robi Insert

insert (string, index, substring) => string

lubię to

insert("Hello ", 6, "world");
// => "Hello world"
svarog
źródło
Nie przeze mnie, ale prawdopodobnie dlatego, że w pytaniu nie było wzmianki o tej bibliotece. Ale nie wydaje się również wykluczać innych bibliotek IMO ..
Dennis98
1
Mimo że nie lubię używać bibliotek, chyba że jest to konieczne, głosowałem za odrzuceniem głosowania negatywnego: P
froggomad
3

próbować

a.slice(0,position) + b + a.slice(position)

lub wyrażenie regularne

"I want apple".replace(/^(.{6})/,"$1 an")

Kamil Kiełczewski
źródło
2
var array = a.split(' '); 
array.splice(position, 0, b);
var output = array.join(' ');

Byłoby to wolniejsze, ale zajmie się dodaniem miejsca przed i po. Również będziesz musiał zmienić wartość pozycji (do 2, teraz jest bardziej intuicyjna)

Ravindra Sane
źródło
2

Szybka naprawa! Jeśli nie chcesz ręcznie dodawać spacji, możesz to zrobić:

var a = "I want apple";
var b = "an";
var position = 6;
var output = [a.slice(0, position + 1), b, a.slice(position)].join('');
console.log(output);

(edytuj: widzę, że tak naprawdę na powyższą odpowiedź odpowiem, przepraszam!)

K. Yu
źródło
2

Jeśli lookbehind ES2018 jest dostępny , jedno rozwiązanie bardziej regexp, że korzysta z niego do „zastąpienia” przy zerowej szerokości pozycji po znaku n-ty (podobny do @Kamil Kiełczewski, ale bez zapisywania początkowych znaków w grupie przechwytywania):

"I want apple".replace(/(?<=^.{6})/, " an")

dlauzon
źródło
1

Cóż, tylko mała zmiana, ponieważ powyższe rozwiązanie daje wynik

"Chcę jabłko"

zamiast

"Chcę jabłko"

Aby uzyskać wynik jako

"Chcę jabłko"

użyj następującego zmodyfikowanego kodu

var output = a.substr(0, position) + " " + b + a.substr(position);
Clyde Lobo
źródło
13
tak, prawdopodobnie nie jest to w tym przypadku pożądane , ale automatyczne dodanie dodatkowej przestrzeni prawie na pewno nie jest pożądane we wszystkich przypadkach.
nickf
12
Czy poprawnym rozwiązaniem nie byłoby dodanie spacji w ciągu = „an”, w ten sposób można ponownie użyć funkcji
Tosh