2010-02-04 39 views
54

Tôi cần loại bỏ sự xuất hiện đầu tiên (và CHỈ là đầu tiên) của một chuỗi từ một chuỗi khác.C# - Cách đơn giản nhất để loại bỏ sự xuất hiện đầu tiên của chuỗi con từ một chuỗi khác

Dưới đây là ví dụ thay thế chuỗi "\\Iteration". Đây:

 
ProjectName\\Iteration\\Release1\\Iteration1 

sẽ trở thành này:

 
ProjectName\\Release1\\Iteration1 

Dưới đây một số mã mà thực hiện điều này:

const string removeString = "\\Iteration"; 
int index = sourceString.IndexOf(removeString); 
int length = removeString.Length; 
String startOfString = sourceString.Substring(0, index); 
String endOfString = sourceString.Substring(index + length); 
String cleanPath = startOfString + endOfString; 

Đó có vẻ như rất nhiều mã.

Vì vậy, câu hỏi của tôi là: Có cách nào gọn gàng hơn/dễ đọc hơn/ngắn gọn hơn để thực hiện việc này không?

Trả lời

106
int index = sourceString.IndexOf(removeString); 
string cleanPath = (index < 0) 
    ? sourceString 
    : sourceString.Remove(index, removeString.Length); 
+8

Câu trả lời này có thể vi phạm các chuỗi liên quan đến các ký tự không phải ASCII. Ví dụ, dưới văn hóa en-US, 'æ' và' ae' được coi là bằng nhau. Cố gắng loại bỏ 'paedia' khỏi' Encyclopædia' sẽ ném một 'ArgumentOutOfRangeException', vì bạn đang cố gắng loại bỏ 6 ký tự khi chuỗi con phù hợp chỉ chứa 5. – Douglas

+1

Chúng ta có thể sửa đổi nó như sau:' sourceString.IndexOf (removeString, StringComparison. Ordinal) 'để tránh ngoại lệ. –

23
string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length); 

EDIT: @OregonGhost là đúng. Bản thân tôi sẽ phá vỡ kịch bản với các điều kiện để kiểm tra sự xuất hiện như vậy, nhưng tôi đã hoạt động theo giả định rằng các chuỗi được trao cho nhau thuộc về một số yêu cầu. Có thể quy tắc xử lý ngoại lệ do doanh nghiệp yêu cầu được dự kiến ​​sẽ bắt được khả năng này. Bản thân tôi sẽ sử dụng một vài dòng phụ để thực hiện kiểm tra có điều kiện và cũng để làm cho nó dễ đọc hơn một chút đối với các nhà phát triển trẻ, những người có thể không dành thời gian để đọc nó đủ kỹ lưỡng.

+6

này sẽ sụp đổ nếu removeString không chứa trong sourceString. – OregonGhost

10

Đã viết một TDD thử nghiệm nhanh cho

[TestMethod] 
    public void Test() 
    { 
     var input = @"ProjectName\Iteration\Release1\Iteration1"; 
     var pattern = @"\\Iteration"; 

     var rgx = new Regex(pattern); 
     var result = rgx.Replace(input, "", 1); 

     Assert.IsTrue(result.Equals(@"ProjectName\Release1\Iteration1")); 
    } 

rgx.Replace này (đầu vào, "", 1); nói để tìm đầu vào cho bất kỳ thứ gì khớp với mẫu, với "", 1 lần.

+2

Giống như bạn đã giải quyết được vấn đề. Chỉ cần xem xét hiệu suất khi sử dụng regex cho một vấn đề như thế này. – Thomas

6

Bạn có thể sử dụng phương thức mở rộng để giải trí. Thông thường, tôi không khuyên bạn nên gắn các phương thức mở rộng vào một lớp mục đích chung như chuỗi, nhưng như tôi đã nói đây là điều thú vị. Tôi đã mượn câu trả lời của @ Luke vì không có điểm nào trong việc tái phát minh ra bánh xe.

[Test] 
public void Should_remove_first_occurrance_of_string() { 

    var source = "ProjectName\\Iteration\\Release1\\Iteration1"; 

    Assert.That(
     source.RemoveFirst("\\Iteration"), 
     Is.EqualTo("ProjectName\\Release1\\Iteration1")); 
} 

public static class StringExtensions { 
    public static string RemoveFirst(this string source, string remove) { 
     int index = source.IndexOf(remove); 
     return (index < 0) 
      ? source 
      : source.Remove(index, remove.Length); 
    } 
} 
+0

Tại sao bạn thường không khuyên bạn nên gắn các phương thức mở rộng vào một lớp mục đích chung như String? Những nhược điểm rõ ràng ở đây là gì? –

2

Tôi chắc chắn đồng ý rằng điều này là hoàn hảo cho một phương pháp khuyến nông, nhưng tôi nghĩ rằng nó có thể được cải thiện một chút.

public static string Remove(this string source, string remove, int firstN) 
    { 
     if(firstN <= 0 || string.IsNullOrEmpty(source) || string.IsNullOrEmpty(remove)) 
     { 
      return source; 
     } 
     int index = source.IndexOf(remove); 
     return index < 0 ? source : source.Remove(index, remove.Length).Remove(remove, --firstN); 
    } 

Điều này có một chút đệ quy luôn vui vẻ.

Dưới đây là một thử nghiệm đơn vị đơn giản cũng như:

[TestMethod()] 
    public void RemoveTwiceTest() 
    { 
     string source = "look up look up look it up"; 
     string remove = "look"; 
     int firstN = 2; 
     string expected = " up up look it up"; 
     string actual; 
     actual = source.Remove(remove, firstN); 
     Assert.AreEqual(expected, actual); 

    } 
12
sourceString.Replace(removeString, ""); 
+7

[String.Replace] (https://msdn.microsoft.com/en-us/library/fk49wtc1%28v=vs.110%29.aspx) nói rằng nó "* [r] chuyển thành chuỗi mới trong đó tất cả sự xuất hiện của một chuỗi được chỉ định trong cá thể hiện tại được thay thế bằng một chuỗi được chỉ định * ". OP muốn thay thế ** lần xuất hiện ** đầu tiên. –

+2

Ngoài ra, bạn nên giải thích câu trả lời của mình một chút vì câu trả lời chỉ có mã không được chấp nhận. Hãy xem các câu trả lời khác và so sánh chúng với câu trả lời của bạn cho một số mẹo. –

Các vấn đề liên quan