Birden çok dizeyi birden çok dizeyle değiştirme


213

Bir dizede birden çok kelimeyi başka kelimelerle değiştirmeye çalışıyorum. Dize "Benim bir kedim, bir köpeğim ve bir keçim var."

Ancak, bu "bir köpeğim, bir keçi ve bir kedim var" değil, bunun yerine "bir kedim, bir kedim ve bir kedim var" üretir. Doğru sonucun üretilebilmesi için birden çok dizeyi aynı anda birden çok dizeyle değiştirmek mümkün müdür?

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".

Bir dizede birden çok sözcüğü, daha önce değiştirilmiş sözcükleri değiştirmeden, birden çok başka sözcükle değiştirmek istiyorum.
Anderson Green

i farklı bir sorgu var, eğer kullanıcı dnt bilmek kedi ya da köpek veya keçi (bu rastgele geliyor) girecek biliyorum ama ne zaman bu tür kelime gelecek ben 'hayvan' diyelim yerine değiştirmeniz gerekir. bu senaryo nasıl
edinilir

Yanıtlar:


445

Özel Çözüm

Her birini değiştirmek için bir işlev kullanabilirsiniz.

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

jsfiddle örneği

Genelleme

Normal ifadeyi dinamik bir şekilde korumak ve yalnızca gelecekteki exchange'leri haritaya eklemek istiyorsanız, bunu yapabilirsiniz

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

regex üretmek için. O zaman böyle görünecekti

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

Daha fazla değişiklik eklemek veya değiştirmek için haritayı düzenleyebilirsiniz. 

dinamik regex ile keman

Yeniden Kullanılabilir Yapma

Bunun genel bir desen olmasını istiyorsanız, bunu böyle bir işleve çekebilirsiniz.

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

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

Böylece str'yi ve fonksiyona istediğiniz değişikliklerin haritasını aktarabilirsiniz ve dönüştürülmüş dizeyi döndürür.

işlev ile keman

Object.keys'in eski tarayıcılarda çalıştığından emin olmak için, örneğin MDN veya Es5 gibi bir çoklu dolgu ekleyin .


4
JavaScript dizelerinde izin verilen karakterler (burada kullanılan tuşlar gibi) izin verilen karakterlerle aynı olmadığından, tüm dizeleri değiştirmek için bu işlevi kullanıp kullanamayacağımdan emin değilim. .
Anderson Green

2
javascript özelliği olarak rastgele bir dize kullanabilirsiniz. Önemli değil. .Gösterimi tüm bu özelliklerle kullanamazsınız . Köşeli ayraç notasyonu herhangi bir dize ile çalışır.
Ben McCormick

2
Gerçekten harika çalışıyor. İngilizce çözümlerini (24.973.56 - 24.973,56), kullanarak map={'.': ',', ',': '.'}ve regex olarak değiştirmek için bu çözümü ('spesifik' olan) başarıyla kullanıyorum /\.|,/g.
Sygmoral

5
Bu çözümü seviyorum ama yerine zorunda return mapObj[matched.toLowerCase()];lazım return mapObj[matched];ben küçük harf duyarlı tuşlarını kullanın beri mapObj.
Michal Moravcik

2
Düzenli ifadesi için anahtarları kaçmak isteyebilirsiniz: Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'). Bu yanıttan
robsch

9

Bu, bu durumda tam ihtiyacınızı karşılamayabilir, ancak bunu genel bir çözüm olarak dizelerde birden çok parametreyi değiştirmek için yararlı bir yol buldum. Kaç kez başvurulduklarına bakılmaksızın, parametrelerin tüm örneklerinin yerini alacaktır:

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

Aşağıdaki şekilde çağırırsınız:

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

8

Tekrar değiştirilmesini önlemek için numaralı öğeler kullanın. Örneğin

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

sonra

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

Nasıl çalışır: -% \ d +,% işaretinden sonra gelen sayıları bulur. Parantezler sayıyı yakalar.

Bu sayı (dize olarak) lambda fonksiyonunun ikinci parametresi (n) 'dir.

+ N-1, dizeyi sayıya dönüştürür ve 1, pets dizisini dizinlemek için çıkarılır.

% Sayısı daha sonra dizi dizinindeki dize ile değiştirilir.

/ G, lambda işlevinin her sayı ile art arda çağrılmasına neden olur ve bu da diziden bir dize ile değiştirilir.

Modern JavaScript'te: -

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

İlginç. Değiştirme fonksiyonundaki mantığı açıklayabilir misiniz?
Eric Hepperle - CodeSlayer2010

5

Bu benim için çalıştı:

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"


Dize normal ifade karakterleri içeriyorsa çalışmaz.
Roemer

Hakkında "uzatmayın ...": Ben eşitsizliği büyük / küçük harfe duyarlı olmayan iki dizeyi karşılaştırmak için benim Dize uzattı. Bu işlevsellik String tarafından sağlanmadı, ancak bir gün olabilir ve bu da uygulamaların bozulmasına neden olabilir. "Alt sınıf" veya "Dize" böyle bir işlevi güvenli bir şekilde eklemek için bir yolu var mı, ya da sadece yeni bir iki bağımsız değişken işlev benim uygulama kitaplığının bir parçası olarak tanımlamak gerekir?
David Spector

4

Array.prototype.reduce () kullanarak :

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)

Misal

// /////////////    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


En iyi cevap. Ancak ${f}biriken değer için f yerine kullanmak için bir neden var mı?
David Spector

1
Verilen dizelerin TÜMÜNÜN değiştirilmesini istiyorsanız, yalnızca ilkini değil, g bayrağını ekleyin: "const sonuç1 = arrayOfObjects.reduce ((f, s) => ${f}.replace (new RegExp (Object.keys (s) [ 0], 'g'), s [Object.keys (s) [0]]), cümle1) "
David Spector

2

Birisi orijinal posterin çözümünün neden çalışmadığını merak ederse:

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 ... iyi analiz edildi ... thumbsup
Deepa MG

1

Değiştirilecek deseni tanımlamak için kullanıcı düzenli işlevi ve daha sonra girdi dizesinde çalışmak için değiştirme işlevini kullanma,

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

Eğer farkında değilseniz, ama yanlış cevap olduğunu söyleme. Benim durumum "{" a ": 1," b ": 2}" olduğu gibi yukarıdaki yolu değiştirdim. Eğer başkalarına yardım ederlerse, başkalarına isterse cevap sadece sizin için değildir. @Carr
KARTHIKEYAN.A

Yine, anlamsız bir cevap verdiniz, yaptığınız şey, zaten soruda yapabileceğiniz şeydir, bu cevap insanları yeni düşünebileceklerini ve RegExpnesneyi kullanabileceklerinin sorunu çözebileceğini yanlış yönlendirecektir
Carr

Bu durumda, hala soruyu soran soru ile aynı probleminiz varvar i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

Bir kez değiştir paketimle, aşağıdakileri yapabilirsiniz:

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.'

Bu paket inanılmaz :) Tam beklediğim gibi çalışıyor
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 "Birden fazla dizeyi aynı anda birden çok dizeyle değiştirmek mümkün mü" diye sordu . Bu üç ayrı adımdır.
LittleBobbyTables - Au Revoir

1

Sınırlayıcıları kullanarak dizeyi bulabilir ve değiştirebilirsiniz.

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

/ * replaceSome yöntemi, istediğimiz kadar çok argüman alır ve hepsini, 2013 CopyRights için kaydettiğimiz son argümanla değiştirir: Max Ahmed bu bir örnektir:

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

Bu npm paketini yazdım stringinject https://www.npmjs.com/package/stringinject aşağıdakileri yapmanızı sağlar

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

{0} ve {1} yerine dizi öğelerini koyar ve aşağıdaki dizeyi döndürür

"this is a test string for stringInject"

veya yer tutucuları nesne anahtarları ve aşağıdaki değerlerle değiştirebilirsiniz:

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

"My username is tjcafferkey on Github" 

0

Bu amaçla https://www.npmjs.com/package/union-replacer kullanabilirsiniz . Temelde string.replace(regexp, ...), tam gücünü korurken bir geçişte birden fazla yer değiştirmeye izin veren bir muadildir string.replace(...).

Açıklama: Ben yazarım. Kütüphane, kullanıcı tarafından yapılandırılabilen daha karmaşık değiştirmeleri desteklemek için geliştirilmiştir ve yakalama grupları, geri başvurular ve geri arama işlevi değiştirmeleri gibi tüm sorunlu sorunları giderir.

Yukarıdaki çözümler, kesin dize değiştirme işlemleri için yeterince iyidir.


-1

Ben @BenMcCormicks biraz genişletti. Normal dizeler için çalıştı ama karakterlerden veya joker karakterlerden kaçmış olsaydım değil. İşte yaptığım şey

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)

"falan filan 234433 filan"

Bu şekilde mapObj anahtarıyla eşleşir ve eşleşen kelime ile eşleşmez.


// değersiz: replaceAll ("Bir kedim, bir köpeğim ve bir keçim var.", {cat: "köpek", köpek: "keçi", keçi: "kedi"}) // üretir: "Bir kedim var , bir kedi ve bir kedi. "
devon

-3

Jquery ile çözüm (önce bu dosyayı ekleyin): Birden çok dizeyi birden çok dizeyle değiştirin:

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

Bu çözüm JQuery gerektiriyor mu?
Anderson Green

javascript etiketi söz konusu eklendi ve jquery bir javascript kütüphanesidir.
Süper Model

2
@ Süper hmmm javascript tag added in question, and jquery is a libarary of javascript.bu mantık kapalı, başka bir yol olmalı ve aynı zamanda sadece bir kafa - javascript etiketi bilgi: " Bir çerçeve / kütüphane için başka bir etiket de dahil
değilse

@Anderson Green, evet yukarıdaki senaryo için jquery gerekli.
Süper Model

@ Traxo, çoğu web uygulamasında çerçeve kullanıyoruz (bootstrap / google materyali). Jquery, tüm modern çerçeveleri içerir. Bu nedenle, jquery web uygulamaları için gereklidir.
Süper Model
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.