複数の文字列を他の複数の文字列で置き換える


213

文字列内の複数の単語を他の複数の単語に置き換えようとしています。文字列は「猫、犬、山羊がいます」です。

ただし、「犬、山羊、猫を飼っている」ではなく、「猫、猫、猫を飼っている」という結果になります。JavaScriptで複数の文字列を他の複数の文字列に同時に置換して、正しい結果が生成されるようにすることは可能ですか?

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

文字列内の複数の単語を、既に置き換えられている単語を置き換えることなく、他の複数の単語に置き換えたい。
アンダーソングリーン

私はいくつかの異なるクエリを持っていますが、ユーザーが猫、犬、または山羊を入力することを知っている場合(これはランダムに来ます)ですが、このような単語が来るたびに、「動物」と置き換える必要があります。このシナリオの入手方法
Prasanna Sasne

回答:


445

特定のソリューション

関数を使用して、それぞれを置き換えることができます。

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の例

それを一般化する

正規表現を動的に維持し、将来の交換をマップに追加するだけの場合は、これを行うことができます

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

正規表現を生成します。だからそれはこのようになります

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

さらに置換を追加または変更するには、マップを編集するだけです。 

動的正規表現をいじる

再利用可能にする

これを一般的なパターンにしたい場合は、これを次のような関数に引き出すことができます

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

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

したがって、strと必要な置換のマップを関数に渡すだけで、変換された文字列が返されます。

機能をいじる

Object.keysが古いブラウザで機能するようにするには、MDNEs5などからのポリフィルを追加します。


4
この関数を使用してすべてのタイプの文字列を置き換えることができるかどうかはわかりません。JavaScript文字列で許可される文字は、JavaScript識別子で許可される文字(ここで使用されるキーなど)と同じではないためです。 。
アンダーソングリーン

2
javascriptプロパティとして任意の文字列を使用できます。関係ありません。この.ようなすべてのプロパティで表記法を使用することはできません。ブラケット表記は、どの文字列でも機能します。
ベンマコーミック2013年

2
それは確かに素晴らしい作品です。私はこのソリューション(「特定の」ソリューション)を使用して、英語の表記をヨーロッパの表記(24,973.56から24.973,56)に変更しmap={'.': ',', ',': '.'}、とregex を使用してい/\.|,/gます。
シグモラル2013

5
このソリューションは気に入っていますが、で大文字と小文字を区別するキーを使用return mapObj[matched.toLowerCase()];したreturn mapObj[matched];からといって置き換える必要がありましたmapObj
Michal Moravcik 2014年

2
正規表現のキーをエスケープしたい場合がありますObject.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|')この回答に
robsch

9

これは、この場合の正確なニーズを満たしていない可能性がありますが、一般的な解決策として、これは文字列内の複数のパラメータを置き換える便利な方法であることがわかりました。何回参照されても、パラメーターのすべてのインスタンスを置き換えます。

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

次のように呼び出します。

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

8

番号の付いたアイテムを使用して、再度交換しないようにします。例えば

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

その後

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

仕組み:-%\ d +は、%の後に来る数字を検索します。角かっこは番号をキャプチャします。

この数値(文字列として)は、ラムダ関数の2番目のパラメーターnです。

+ n-1は文字列を数値に変換し、次に1を引いてpets配列のインデックスを作成します。

次に、%numberが配列インデックスの文字列に置き換えられます。

/ gを指定すると、ラムダ関数が各数値で繰り返し呼び出され、配列の文字列に置き換えられます。

最近のJavaScriptでは:-

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

面白い。置換機能のロジックを説明できますか?
エリックHepperle-CodeSlayer2010 '

5

これは私のために働きました:

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"


文字列に正規表現文字が含まれている場合は機能しません。
Roemer

「拡張しない...」について:文字列を拡張して、2つの文字列が等しいかどうかを比較します。大文字と小文字は区別されません。この機能はStringでは提供されていませんが、いつかは提供される可能性があり、アプリが壊れる可能性があります。そのような関数を安全に含めるために文字列を「サブクラス化」または「拡張」する方法はありますか、または単にアプリライブラリの一部として新しい2つの引数を持つ関数を定義する必要がありますか?
David Spector

4

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)

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


ベストアンサー。しかし${f}、累積値にfの代わりに使用する理由はありますか?
David Spector

1
最初の文字列だけでなく、指定した文字列をすべて置換する場合は、gフラグを追加します。 "const result1 = arrayOfObjects.reduce((f、s)=> ${f}.replace(new RegExp(Object.keys(s)[ 0]、 'g')、s [Object.keys(s)[0]])、sentence1) "
David Spector

2

元のポスターのソリューションが機能しない理由を誰かが疑問に思っている場合に備えて:

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

ハハ...よく分析されました... thumbsup
Deepa MG

1

置換するパターンを定義し、次に置換関数を使用して入力文字列を処理するユーザー通常関数

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

あなたがスキップを認識していないが、それが間違った答えであると言わないでください。私のケース "{" a ":1、" b ":2}"は、上記の方法を置き換えるために使用したものです。他の人のためにしたい場合、それが他の人を助ける場合、答えはあなただけではありません。@Carr
KARTHIKEYAN.A

繰り返しますが、あなたは単に無意味な答えを提供しました。あなたがすることは、質問者がすでに質問で行うことができることです。この答えは、人々が新しく考え、RegExpオブジェクトを利用することで問題を解決できると誤解させます
Carr

この場合でも、質問者の質問と同じ問題が発生しますvar i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

私のreplace-onceパッケージを使用すると、次のことができます。

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

このパッケージはすごいです:)期待通りに動作します
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は、「複数の文字列を同時に他の複数の文字列に置き換えることは可能ですか」と尋ねました。これは3つの別個のステップです。
LittleBobbyTables-Au Revoir

1

区切り文字を使用して文字列を検索および置換できます。

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メソッドは文字列を受け取り、必要な数の引数を取り、指定した最後の引数ですべてを置き換えます。2013CopyRights保存対象:Max Ahmedこれは例です

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

私はこのnpmパッケージstringinject https://www.npmjs.com/package/stringinjectを書いたので、次のことができます

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

{0}と{1}を配列項目で置き換え、次の文字列を返します

"this is a test string for stringInject"

または、次のようにプレースホルダーをオブジェクトのキーと値に置き換えることもできます。

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

"My username is tjcafferkey on Github" 

0

この目的でhttps://www.npmjs.com/package/union-replacerを使用できます。これは基本的にはstring.replace(regexp, ...)対応するものであり、の能力を完全に維持しながら、1つのパスで複数の置換を行うことができますstring.replace(...)

開示:私は著者です。ライブラリは、より複雑なユーザー設定可能な置換をサポートするために開発され、キャプチャグループ、バックリファレンス、コールバック関数の置換などの問題のあるすべての問題に対処します。

上記の解決策は、文字列を正確に置き換えるのに十分です。


-1

@BenMcCormicksを少し拡張しました。彼は通常の文字列では機能しましたが、文字やワイルドカードをエスケープした場合は機能しませんでした。これが私がやったことです

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)

"何とか何とか234433何とか何とか"を返します

このようにして、一致した単語ではなく、mapObjのキーに一致します。


//価値がない:replaceAll( "猫、犬、山羊がいます。"、{cat: "dog"、dog: "goat"、goat: "cat"})//生成されるのは: "猫がいます、猫、猫。」
devon

-3

Jqueryを使用したソリューション(最初にこのファイルを含める):複数の文字列を他の複数の文字列で置き換えます。

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

このソリューションにはJQueryが必要ですか?
アンダーソングリーン

問題のjavascriptタグが追加されました。jqueryはjavascriptのライブラリです。
スーパーモデル

2
@Super javascript tag added in question, and jquery is a libarary of javascript.Hmmmロジックがオフになっているため、逆方向である必要があります。また、注意が必要です-JavaScript タグ情報から:「フレームワーク/ライブラリの別のタグも含まれていない限り、純粋なJavaScriptの回答が期待されます。
Traxo

@アンダーソン・グリーン、はい、上記のスクリプトにはjqueryが必要です。
スーパーモデル

@ Traxo、ほとんどのWebアプリケーションでフレームワーク(bootstrap / googleマテリアル)を使用しています。jqueryはすべての最新のフレームワークに含まれています。したがって、jqueryはWebアプリケーションに必要なアイテムです。
スーパーモデル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.