ฉันจะแทนที่ * อินสแตนซ์แรก * ของสตริงใน. NET ได้อย่างไร


108

ฉันต้องการแทนที่เหตุการณ์แรกในสตริงที่กำหนด

ฉันจะทำสิ่งนี้ให้สำเร็จใน. NET ได้อย่างไร?


กรุณาตั้งกระทู้ที่ชัดเจนให้คนเข้าใจได้ ฉันแก้ไขอันนี้ให้คุณด้วย คุณควรระบุภาษาอย่างน้อยที่นี่
GEOCHET

แน่นอนว่ามันไม่เคยถูกแทนที่ ... มันเป็นสตริงใหม่ที่มีสตริงเดิมพร้อมข้อความแทนที่เสมอ เนื่องจากสตริงไม่เปลี่ยนรูป
Pablo Marambio

ฉันลองใช้เมธอด `String.Replace ()` แต่มันแทนที่ "AA" ทั้งหมดด้วย "XQ"
Thorin Oakenshield

2
คำถามนี้ - stackoverflow.com/questions/141045/… - เปิดเผยทุกอย่างเกี่ยวกับสิ่งที่คุณต้องทำ
stack72

1
หมายเหตุ: รวมกับคำถามอื่นที่คล้ายกันซึ่งใช้ "AA" => "XQ" เป็นตัวอย่างในการค้นหา / แทนที่
Marc Gravell

คำตอบ:


134
string ReplaceFirst(string text, string search, string replace)
{
  int pos = text.IndexOf(search);
  if (pos < 0)
  {
    return text;
  }
  return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}

ตัวอย่าง:

string str = "The brown brown fox jumps over the lazy dog";

str = ReplaceFirst(str, "brown", "quick");

แก้ไข : ตามที่ @itsmatt กล่าวไว้นอกจากนี้ยังมี Regex.Replace (String, String, Int32) ซึ่งสามารถทำได้เช่นเดียวกัน แต่อาจมีราคาแพงกว่าในรันไทม์เนื่องจากใช้ตัวแยกวิเคราะห์ที่มีคุณลักษณะครบถ้วนซึ่งวิธีการของฉันค้นหาหนึ่งรายการและสามสตริง การต่อกัน

แก้ไข 2 : หากเป็นงานทั่วไปคุณอาจต้องการทำให้เมธอดเป็นวิธีการขยาย:

public static class StringExtension
{
  public static string ReplaceFirst(this string text, string search, string replace)
  {
     // ...same as above...
  }
}

จากตัวอย่างด้านบนตอนนี้คุณสามารถเขียน:

str = str.ReplaceFirst("brown", "quick");

2
น่าสนใจคุณได้ทดสอบสมมติฐานของคุณเกี่ยวกับวิธีการ regex ที่มีราคาแพงกว่าในรันไทม์หรือไม่? แล้วความเร็วล่ะ? บางทีการค้นหาโดยใช้ Regex จะเร็วกว่าการใช้ IndexOf?
mfloryan

ฉันชอบคำตอบของ @BilltheLizard ที่เกี่ยวข้องกับ Remove () และ Insert () มากกว่าวิธีนี้ที่เกี่ยวข้องกับ Substring () มีพื้นฐานใดบ้างที่จะบอกว่าหนึ่งดีกว่าอีกอัน?
JohnC

3
ระวัง: สิ่งนี้ใช้ไม่ได้กับ Unicode ที่รวมอักขระหรือตัวอักษรควบ ตัวอย่างเช่นReplaceFirst("oef", "œ", "i")ส่งคืน "ief" แทน "if" ไม่ถูกต้อง ดูคำถามนี้สำหรับข้อมูลเพิ่มเติม
Michael Liu

2
ReSharper String.IndexOf is culture specific.เตือน int pos = text.IndexOf(search, StringComparison.Ordinal);มีประสิทธิภาพมากขึ้นเพื่ออัปเดต
Contango

64

ดังที่itsmattกล่าวว่าRegex.Replaceเป็นทางเลือกที่ดีสำหรับสิ่งนี้อย่างไรก็ตามเพื่อให้คำตอบของเขาสมบูรณ์ยิ่งขึ้นฉันจะเติมด้วยตัวอย่างโค้ด:

using System.Text.RegularExpressions;
...
Regex regex = new Regex("foo");
string result = regex.Replace("foo1 foo2 foo3 foo4", "bar", 1);             
// result = "bar1 foo2 foo3 foo4"

พารามิเตอร์ที่สามตั้งค่าเป็น 1 ในกรณีนี้คือจำนวนครั้งที่เกิดขึ้นของรูปแบบนิพจน์ทั่วไปที่คุณต้องการแทนที่ในสตริงอินพุตจากจุดเริ่มต้นของสตริง

ฉันหวังว่าสิ่งนี้จะทำได้ด้วยRegexแบบคงที่แทนที่การโอเวอร์โหลด แต่น่าเสียดายที่ดูเหมือนว่าคุณต้องมีอินสแตนซ์ Regex เพื่อทำให้สำเร็จ


1
ผลงานที่แท้จริง"foo"แต่คุณกำลังจะต้องการสำหรับเป็นรูปเป็นร่างnew Regex(Regex.Escape("foo")) "foo"
ruffin

17

ลองดูที่Regex.Replace


2
โดยเฉพาะ Regex.Replace Method (String, String, Int32) จะทำเคล็ดลับและกระชับจริงๆ
itsmatt

15

โดยคำนึงถึง "รายแรกเท่านั้น" อาจ:

int index = input.IndexOf("AA");
if (index >= 0) output = input.Substring(0, index) + "XQ" +
     input.Substring(index + 2);

เหรอ?

หรือโดยทั่วไป:

public static string ReplaceFirstInstance(this string source,
    string find, string replace)
{
    int index = source.IndexOf(find);
    return index < 0 ? source : source.Substring(0, index) + replace +
         source.Substring(index + find.Length);
}

จากนั้น:

string output = input.ReplaceFirstInstance("AA", "XQ");

11
using System.Text.RegularExpressions;

RegEx MyRegEx = new RegEx("F");
string result = MyRegex.Replace(InputString, "R", 1);

จะได้พบกับครั้งแรกFในและแทนที่ด้วยInputStringR


2
ฉันทำให้มันง่ายขึ้นเป็นซับresult = (New Regex("F")).Replace(InputString, "R", 1)
cjbarth

คำตอบที่ดีที่สุดที่นี่ (ร่วมกับ cjbarth)
Todd Vance

8

วิธีการขยาย C # ที่จะทำสิ่งนี้:

public static class StringExt
{
    public static string ReplaceFirstOccurrence(this string s, string oldValue, string newValue)
    {
         int i = s.IndexOf(oldValue);
         return s.Remove(i, oldValue.Length).Insert(i, newValue);    
    } 
}

สนุก


ขอบคุณ! ฉันแก้ไขสิ่งนี้เพื่อสร้างเมธอดส่วนขยาย "RemoveFirst" ซึ่ง ... ลบการเกิดครั้งแรกของอักขระออกจากสตริง
pbh101

4
สิ่งนี้จะล้มเหลวหาก oldValue ไม่ได้เป็นส่วนหนึ่งของสตริง
VVS


4

และเนื่องจากยังมี VB.NET ที่ต้องพิจารณาฉันจึงขอเสนอ:

Private Function ReplaceFirst(ByVal text As String, ByVal search As String, ByVal replace As String) As String
    Dim pos As Integer = text.IndexOf(search)
    If pos >= 0 Then
        Return text.Substring(0, pos) + replace + text.Substring(pos + search.Length)
    End If
    Return text 
End Function

4

สมมติว่าAAจำเป็นต้องเปลี่ยนก็ต่อเมื่ออยู่ที่จุดเริ่มต้นของสตริง:

var newString;
if(myString.StartsWith("AA"))
{
  newString ="XQ" + myString.Substring(2);
}

หากคุณต้องการแทนที่เหตุการณ์แรกAAไม่ว่าสตริงจะขึ้นต้นด้วยหรือไม่ก็ตามให้ใช้วิธีแก้ปัญหาจาก Marc


3

หนึ่งในการโอเวอร์โหลดRegex.Replaceใช้เวลาintสำหรับ "จำนวนครั้งสูงสุดที่สามารถทดแทนได้" เห็นได้ชัดว่าการใช้Regex.Replaceสำหรับการแทนที่ข้อความธรรมดาอาจดูเหมือนการใช้งานมากเกินไป แต่ก็รัดกุม:

string output = (new Regex("AA")).Replace(input, "XQ", 1);


1

ตัวอย่างนี้สรุปสตริงย่อย (แต่ช้ากว่า) แต่อาจเร็วกว่า RegEx มาก:

var parts = contents.ToString().Split(new string[] { "needle" }, 2, StringSplitOptions.None);
return parts[0] + "replacement" + parts[1];

0

อัปเดตวิธีการขยายSpanเพื่อลดการสร้างสตริงใหม่

    public static string ReplaceFirstOccurrence(this string source, string search, string replace) {
        int index = source.IndexOf(search);
        if (index < 0) return source;
        var sourceSpan = source.AsSpan();
        return string.Concat(sourceSpan.Slice(0, index), replace, sourceSpan.Slice(index + search.Length));
    }

-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.