Thay thế nhiều chuỗi bằng nhiều chuỗi khác


213

Tôi đang cố gắng thay thế nhiều từ trong một chuỗi bằng nhiều từ khác. Chuỗi là "Tôi có một con mèo, một con chó và một con dê."

Tuy nhiên, điều này không tạo ra "Tôi có một con chó, một con dê và một con mèo", mà thay vào đó nó tạo ra "Tôi có một con mèo, một con mèo và một con mèo". Có thể thay thế nhiều chuỗi bằng nhiều chuỗi khác cùng một lúc trong JavaScript, để kết quả chính xác sẽ được tạo ra không?

var str = "I have a cat, a dog, and a goat.";
str = str.replace(/cat/gi, "dog");
str = str.replace(/dog/gi, "goat");
str = str.replace(/goat/gi, "cat");

//this produces "I have a cat, a cat, and a cat"
//but I wanted to produce the string "I have a dog, a goat, and a cat".

Tôi muốn thay thế nhiều từ trong một chuỗi bằng nhiều từ khác, mà không thay thế các từ đã được thay thế.
Anderson Green

Tôi có một số truy vấn khác nhau, nếu tôi không biết người dùng sẽ nhập mèo hay chó hoặc dê (điều này sẽ đến một cách ngẫu nhiên) nhưng bất cứ khi nào từ này sẽ xuất hiện, tôi cần thay thế bằng 'động vật'. làm thế nào để có được kịch bản này
Prasanna Sasne

Câu trả lời:


445

Giải pháp cụ thể

Bạn có thể sử dụng một chức năng để thay thế từng cái.

var str = "I have a cat, a dog, and a goat.";
var mapObj = {
   cat:"dog",
   dog:"goat",
   goat:"cat"
};
str = str.replace(/cat|dog|goat/gi, function(matched){
  return mapObj[matched];
});

ví dụ jsfiddle

Tổng quát hóa nó

Nếu bạn muốn tự động duy trì regex và chỉ cần thêm các trao đổi trong tương lai vào bản đồ, bạn có thể làm điều này

new RegExp(Object.keys(mapObj).join("|"),"gi"); 

để tạo regex. Vì vậy, nó sẽ trông như thế này

var mapObj = {cat:"dog",dog:"goat",goat:"cat"};

var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
str = str.replace(re, function(matched){
  return mapObj[matched];
});

Và để thêm hoặc thay đổi bất kỳ thay thế nào nữa, bạn chỉ cần chỉnh sửa bản đồ. 

Fiddle với regex năng động

Làm cho nó có thể tái sử dụng

Nếu bạn muốn đây là một mô hình chung, bạn có thể kéo nó ra một chức năng như thế này

function replaceAll(str,mapObj){
    var re = new RegExp(Object.keys(mapObj).join("|"),"gi");

    return str.replace(re, function(matched){
        return mapObj[matched.toLowerCase()];
    });
}

Vì vậy, sau đó bạn có thể chỉ cần vượt qua str và bản đồ của các thay thế bạn muốn cho hàm và nó sẽ trả về chuỗi đã chuyển đổi.

Fiddle với chức năng

Để đảm bảo Object.keys hoạt động trong các trình duyệt cũ hơn, hãy thêm một polyfill, ví dụ từ MDN hoặc Es5 .


4
Tôi không chắc mình có thể sử dụng chức năng này để thay thế tất cả các loại chuỗi hay không, vì các ký tự được phép trong chuỗi JavaScript không giống với các ký tự được phép trong mã định danh JavaScript (chẳng hạn như các khóa được sử dụng ở đây) .
Anderson Green

2
bạn có thể sử dụng một chuỗi tùy ý trong như một thuộc tính javascript. Không nên quan trọng. Bạn không thể sử dụng .ký hiệu với tất cả các thuộc tính như vậy. Ký hiệu chân đế hoạt động với bất kỳ chuỗi.
Ben McCormick

2
Nó thực sự hoạt động tuyệt vời. Tôi thành công khi sử dụng giải pháp này (một 'cụ thể') để thay đổi các ký hiệu số tiếng Anh thành các ký hiệu châu Âu (24.973,56 thành 24.973,56), sử dụng map={'.': ',', ',': '.'}và biểu thức chính quy /\.|,/g.
Sygmoral

5
Tôi thích giải pháp này nhưng tôi phải thay thế return mapObj[matched.toLowerCase()];chỉ return mapObj[matched];vì tôi sử dụng các phím nhạy trong trường hợp mapObj.
Michal Moravcik

2
Bạn có thể muốn thoát các phím cho biểu thức thông thường : Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'). Lấy cảm hứng từ câu trả lời này
robsch

9

Điều này có thể không đáp ứng nhu cầu chính xác của bạn trong trường hợp này, nhưng tôi đã thấy đây là một cách hữu ích để thay thế nhiều tham số trong chuỗi, như một giải pháp chung. Nó sẽ thay thế tất cả các phiên bản của các tham số, bất kể chúng được tham chiếu bao nhiêu lần:

String.prototype.fmt = function (hash) {
        var string = this, key; for (key in hash) string = string.replace(new RegExp('\\{' + key + '\\}', 'gm'), hash[key]); return string
}

Bạn sẽ gọi nó như sau:

var person = '{title} {first} {last}'.fmt({ title: 'Agent', first: 'Jack', last: 'Bauer' });
// person = 'Agent Jack Bauer'

8

Sử dụng các mục được đánh số để ngăn thay thế một lần nữa. ví dụ

let str = "I have a %1, a %2, and a %3";
let pets = ["dog","cat", "goat"];

sau đó

str.replace(/%(\d+)/g, (_, n) => pets[+n-1])

Cách thức hoạt động: -% \ d + tìm các số đứng sau%. Các dấu ngoặc bắt số.

Số này (dưới dạng chuỗi) là tham số thứ 2, n, cho hàm lambda.

+ N-1 chuyển đổi chuỗi thành số sau đó trừ đi 1 để lập chỉ mục cho mảng vật nuôi.

Số% sau đó được thay thế bằng chuỗi tại chỉ mục mảng.

/ G làm cho hàm lambda được gọi liên tục với mỗi số được thay thế bằng một chuỗi từ mảng.

Trong JavaScript hiện đại: -

replace_n=(str,...ns)=>str.replace(/%(\d+)/g,(_,n)=>ns[n-1])

Hấp dẫn. Bạn có thể giải thích logic trong chức năng thay thế?
Eric Hepperle - CodeSlayer2010

5

Điều này làm việc cho tôi:

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

function replaceAll(str, map){
    for(key in map){
        str = str.replaceAll(key, map[key]);
    }
    return str;
}

//testing...
var str = "bat, ball, cat";
var map = {
    'bat' : 'foo',
    'ball' : 'boo',
    'cat' : 'bar'
};
var new = replaceAll(str, map);
//result: "foo, boo, bar"


Không hoạt động nếu chuỗi chứa các ký tự regex.
RoTable

Về "không mở rộng ...": Tôi đã mở rộng Chuỗi của mình để so sánh hai chuỗi về sự bình đẳng, không phân biệt chữ hoa chữ thường. Chức năng này không được String cung cấp, nhưng có thể một ngày nào đó, điều này có thể khiến các ứng dụng của tôi bị hỏng. Có cách nào để chuỗi "lớp con" hoặc "mở rộng" để bao gồm một hàm như vậy một cách an toàn không, hay tôi chỉ nên định nghĩa một hàm hai đối số mới là một phần của thư viện ứng dụng của mình?
David Spector

4

sử dụng Array.prototype.reduce () :

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence = 'plants are smart'

arrayOfObjects.reduce(
  (f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence
)

// as a reusable function
const replaceManyStr = (obj, sentence) => obj.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

const result = replaceManyStr(arrayOfObjects , sentence1)

Thí dụ

// /////////////    1. replacing using reduce and objects

// arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

// replaces the key in object with its value if found in the sentence
// doesn't break if words aren't found

// Example

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence1 = 'plants are smart'
const result1 = arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence1)

console.log(result1)

// result1: 
// men are dumb


// Extra: string insertion python style with an array of words and indexes

// usage

// arrayOfWords.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence)

// where arrayOfWords has words you want to insert in sentence

// Example

// replaces as many words in the sentence as are defined in the arrayOfWords
// use python type {0}, {1} etc notation

// five to replace
const sentence2 = '{0} is {1} and {2} are {3} every {5}'

// but four in array? doesn't break
const words2 = ['man','dumb','plants','smart']

// what happens ?
const result2 = words2.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence2)

console.log(result2)

// result2: 
// man is dumb and plants are smart every {5}

// replaces as many words as are defined in the array
// three to replace
const sentence3 = '{0} is {1} and {2}'

// but five in array
const words3 = ['man','dumb','plant','smart']

// what happens ? doesn't break
const result3 = words3.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence3)

console.log(result3)

// result3: 
// man is dumb and plants


Câu trả lời tốt nhất. Nhưng có một lý do để sử dụng ${f}thay vì f cho giá trị tích lũy?
David Spector

1
Nếu bạn muốn TẤT CẢ các chuỗi đã cho được thay thế, không chỉ chuỗi đầu tiên, hãy thêm cờ g: "const result1 = ArrayOfObjects.reduce ((f, s) => ${f}.replace (new RegExp (Object.keys (s) [ 0], 'g'), s [Object.keys (s) [0]]), câu1) "
David Spector

2

Chỉ trong trường hợp ai đó đang tự hỏi tại sao giải pháp của người gửi ban đầu không hoạt động:

var str = "I have a cat, a dog, and a goat.";

str = str.replace(/cat/gi, "dog");
// now str = "I have a dog, a dog, and a goat."

str = str.replace(/dog/gi, "goat");
// now str = "I have a goat, a goat, and a goat."

str = str.replace(/goat/gi, "cat");
// now str = "I have a cat, a cat, and a cat."

ha ha ... phân tích tốt ... ngón tay cái
Deepa MG

1

Hàm thường dùng của người dùng để xác định mẫu cần thay thế và sau đó sử dụng hàm thay thế để làm việc trên chuỗi đầu vào,

var i = new RegExp('"{','g'),
    j = new RegExp('}"','g'),
    k = data.replace(i,'{').replace(j,'}');

Nếu bạn không biết bỏ qua, nhưng đừng nói đó là câu trả lời sai. Trường hợp của tôi "{" a ": 1," b ": 2}" như thế tôi đã sử dụng để thay thế cách trên. Nếu nó giúp người khác nếu họ muốn khác, câu trả lời không chỉ dành cho bạn. @Carr
KARTHIKEYAN.A

Một lần nữa, bạn vừa đưa ra một câu trả lời vô nghĩa, những gì bạn làm là người hỏi đã có thể làm trong câu hỏi, câu trả lời này sẽ đánh lừa mọi người rằng họ có thể nghĩ mới và sử dụng RegExpđối tượng có thể giải quyết vấn đề
Carr

Trong trường hợp này, bạn vẫn gặp vấn đề tương tự như câu hỏi của người hỏi khi bạn thực hiệnvar i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

Với gói thay thế một lần của tôi , bạn có thể làm như sau:

const replaceOnce = require('replace-once')

var str = 'I have a cat, a dog, and a goat.'
var find = ['cat', 'dog', 'goat']
var replace = ['dog', 'goat', 'cat']
replaceOnce(str, find, replace, 'gi')
//=> 'I have a dog, a goat, and a cat.'

Gói này thật tuyệt vời :) Hoạt động chính xác như tôi mong đợi
Vishnu Prassad

1
    var str = "I have a cat, a dog, and a goat.";

    str = str.replace(/goat/i, "cat");
    // now str = "I have a cat, a dog, and a cat."

    str = str.replace(/dog/i, "goat");
    // now str = "I have a cat, a goat, and a cat."

    str = str.replace(/cat/i, "dog");
    // now str = "I have a dog, a goat, and a cat."

3
OP đã hỏi "Có thể thay thế nhiều chuỗi bằng nhiều chuỗi khác cùng một lúc không ". Đây là ba bước riêng biệt.
LittleBulkTables - Au Revoir

1

Bạn có thể tìm và thay thế chuỗi bằng cách sử dụng dấu phân cách.

var obj = {
  'firstname': 'John',
  'lastname': 'Doe'
}

var text = "My firstname is {firstname} and my lastname is {lastname}"

console.log(mutliStringReplace(obj,text))

function mutliStringReplace(object, string) {
      var val = string
      var entries = Object.entries(object);
      entries.forEach((para)=> {
          var find = '{' + para[0] + '}'
          var regExp = new RegExp(find,'g')
       val = val.replace(regExp, para[1])
    })
  return val;
}


0
String.prototype.replaceSome = function() {
    var replaceWith = Array.prototype.pop.apply(arguments),
        i = 0,
        r = this,
        l = arguments.length;
    for (;i<l;i++) {
        r = r.replace(arguments[i],replaceWith);
    }
    return r;
}

/ * phương thức thay thế một số chuỗi cần có, nhiều đối số như chúng ta muốn và thay thế tất cả chúng bằng đối số cuối cùng mà chúng ta đã chỉ định 2013 CopyRights được lưu cho: Max Ahmed đây là một ví dụ:

var string = "[hello i want to 'replace x' with eat]";
var replaced = string.replaceSome("]","[","'replace x' with","");
document.write(string + "<br>" + replaced); // returns hello i want to eat (without brackets)

* /

jsFiddle: http://jsfiddle.net/CPj89/


0
<!DOCTYPE html>
<html>
<body>



<p id="demo">Mr Blue 
has a           blue house and a blue car.</p>

<button onclick="myFunction()">Try it</button>

<script>
function myFunction() {
    var str = document.getElementById("demo").innerHTML;
    var res = str.replace(/\n| |car/gi, function myFunction(x){

if(x=='\n'){return x='<br>';}
if(x==' '){return x='&nbsp';}
if(x=='car'){return x='BMW'}
else{return x;}//must need



});

    document.getElementById("demo").innerHTML = res;
}
</script>

</body>
</html>

0

Tôi đã viết chuỗi ký tự npm này https://www.npmjs.com/package/opesinject cho phép bạn thực hiện các thao tác sau

var string = stringInject("this is a {0} string for {1}", ["test", "stringInject"]);

sẽ thay thế {0} và {1} bằng các mục mảng và trả về chuỗi sau

"this is a test string for stringInject"

hoặc bạn có thể thay thế trình giữ chỗ bằng các khóa đối tượng và giá trị như vậy:

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

"My username is tjcafferkey on Github" 

0

Bạn có thể sử dụng https://www.npmjs.com/package/union-replacer cho mục đích này. Về cơ bản, nó là một bản string.replace(regexp, ...)sao, cho phép nhiều sự thay thế xảy ra trong một lượt trong khi vẫn bảo toàn toàn bộ sức mạnh string.replace(...).

Tiết lộ: Tôi là tác giả. Thư viện được phát triển để hỗ trợ các thay thế có thể định cấu hình người dùng phức tạp hơn và nó giải quyết tất cả những vấn đề có vấn đề như các nhóm bắt giữ, phản hồi và thay thế chức năng gọi lại.

Các giải pháp trên là đủ tốt để thay thế chuỗi chính xác mặc dù.


-1

Tôi đã mở rộng trên @BenMcCormicks một chút. Anh ta làm việc cho các chuỗi thông thường nhưng không phải nếu tôi đã thoát khỏi các ký tự hoặc ký tự đại diện. Đây là những gì tôi đã làm

str = "[curl] 6: blah blah 234433 blah blah";
mapObj = {'\\[curl] *': '', '\\d: *': ''};


function replaceAll (str, mapObj) {

    var arr = Object.keys(mapObj),
        re;

    $.each(arr, function (key, value) {
        re = new RegExp(value, "g");
        str = str.replace(re, function (matched) {
            return mapObj[value];
        });
    });

    return str;

}
replaceAll(str, mapObj)

trả lại "blah blah 234433 blah blah"

Bằng cách này, nó sẽ khớp với khóa trong mapObj chứ không phải từ phù hợp '


// vô giá trị: thayTất cả ("Tôi có một con mèo, một con chó và một con dê.", {cat: "dog", dog: "dê", dê: "cat"}) // tạo ra: "Tôi có một con mèo , một con mèo và một con mèo. "
devon

-3

Giải pháp với Jquery (đầu tiên bao gồm tệp này): Thay thế nhiều chuỗi bằng nhiều chuỗi khác:

var replacetext = {
    "abc": "123",
    "def": "456"
    "ghi": "789"
};

$.each(replacetext, function(txtorig, txtnew) {
    $(".eng-to-urd").each(function() {
        $(this).text($(this).text().replace(txtorig, txtnew));
    });
});

Giải pháp này có yêu cầu JQuery không?
Anderson Green

thẻ javascript được thêm vào trong câu hỏi và jquery là một tên khốn của javascript.
Siêu mẫu

2
@Super javascript tag added in question, and jquery is a libarary of javascript.Hmmm logic đó bị tắt, nó phải theo cách khác và cũng chỉ là một cái đầu - từ thông tin thẻ javascript: " Trừ khi một thẻ khác cho khung / thư viện cũng được bao gồm, một câu trả lời JavaScript thuần túy được mong đợi. "
Traxo

@Anderson Green, có jquery cần thiết cho kịch bản trên.
Siêu mẫu

@ Traxo, trong hầu hết các ứng dụng web, chúng tôi đang sử dụng framework (tài liệu bootstrap / google). Jquery bao gồm trong tất cả các khuôn khổ hiện đại. Vì vậy, jquery là mục cần thiết cho các ứng dụng web.
Siêu mẫu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.