Nhận chuỗi con - mọi thứ trước một số ký tự nhất định


124

Tôi đang cố gắng tìm ra cách tốt nhất để có được mọi thứ trước ký tự - trong một chuỗi. Dưới đây là một số chuỗi ví dụ. Độ dài của chuỗi trước đó - thay đổi và có thể dài bất kỳ

223232-1.jpg
443-2.jpg
34443553-5.jpg

vì vậy tôi cần giá trị từ chỉ mục bắt đầu từ 0 đến ngay trước -. Vì vậy, các chuỗi con sẽ trở thành 223232, 443 và 34443553

Câu trả lời:


144

Ví dụ .Net Fiddle

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("223232-1.jpg".GetUntilOrEmpty());
        Console.WriteLine("443-2.jpg".GetUntilOrEmpty());
        Console.WriteLine("34443553-5.jpg".GetUntilOrEmpty());

        Console.ReadKey();
    }
}

static class Helper
{
    public static string GetUntilOrEmpty(this string text, string stopAt = "-")
    {
        if (!String.IsNullOrWhiteSpace(text))
        {
            int charLocation = text.IndexOf(stopAt, StringComparison.Ordinal);

            if (charLocation > 0)
            {
                return text.Substring(0, charLocation);
            }
        }

        return String.Empty;
    }
}

Các kết quả:

223232
443
34443553
344

34

2
Hãy làm cho họ một đặc ân và thêm kiểm tra lỗi cũng giả sử ông có kế hoạch để thực hiện một chức năng ra khỏi :) này
Josh

Cảm ơn Tôi đã gần đến điều này, nhưng tò mò nếu có ai có cách khác để làm điều đó ngoài combo này. Nhưng có, nó hoạt động tốt và vẫn còn khá ngắn.
Tích cựcGuy

14
Nếu bạn muốn có một one-liner mà không làm mất đúng đắn "không tìm thấy" kiểm tra sau đó bạn có thể làm một cái gì đó như thế này:string result = source.Substring(0, Math.Max(source.IndexOf('-'), 0))
LukeH

2
Thay vì s.Substring(0, n)người ta có thể sử dụng s.Remove(n)khi biết (như ở đây) rằng độ dài của chuỗi svượt quá nghiêm ngặt n.
Jeppe Stig Nielsen

@LukeH Nếu IndexOf trả về -1 trong ví dụ của bạn, thì một chuỗi trống sẽ được trả về, phải không?
nghiền nát

124

Sử dụng chức năng chia nhỏ .

static void Main(string[] args)
{
    string s = "223232-1.jpg";
    Console.WriteLine(s.Split('-')[0]);
    s = "443-2.jpg";
    Console.WriteLine(s.Split('-')[0]);
    s = "34443553-5.jpg";
    Console.WriteLine(s.Split('-')[0]);

Console.ReadKey();
}

Nếu chuỗi của bạn không có -thì bạn sẽ nhận được toàn bộ chuỗi.


4
Và nếu bạn có nhiều hơn một dấu gạch nối, bạn sẽ nhận được nhiều phần tử trong mảng của mình.
James Dunne

2
Thật vậy, James, vì vậy đây sẽ chỉ là một giải pháp nếu bạn chỉ mong đợi một dấu gạch ngang duy nhất. Tôi cho rằng bạn có thể sử dụng các phương pháp Linq như bỏ qua và tổng hợp để đạt được những gì bạn muốn, nhưng sau đó bạn có nhiều mã hơn các phương pháp đã được đề xuất. Tất cả phụ thuộc vào mức độ bạn biết về dữ liệu đến.
Dominic Cronin

7
Và một vài năm trôi qua, tôi mới nhận ra rằng mình đã quá vội vàng khi thừa nhận quan điểm của James. Câu hỏi hỏi cách tìm chuỗi trước một ký tự nào đó. Do đó, các trường hợp khác của ký tự đó không liên quan và việc lấy [0] sẽ "chỉ hoạt động". Tất nhiên, nó vẫn phụ thuộc vào mức độ tin cậy của chúng ta đối với dữ liệu đến. Điều gì xảy ra nếu không có '-'?
Dominic Cronin

1
Tôi nghĩ rằng @JamesDunne điểm là bằng cách tách thành một mảng, bạn đang tạo ra một loạt các chuỗi không cần thiết - rác không cần thiết.
nghiền nát

1
Tôi sẽ không lo lắng về "rác không cần thiết". Bất kỳ chuỗi bổ sung nào được tạo theo cách này sẽ không thể truy cập được ngay lập tức và do đó được thu thập trong thế hệ 0, thực sự là chi phí cực kỳ thấp. Thiết kế bộ thu gom rác có mục đích rõ ràng là cho phép sử dụng một số lượng lớn các vật dụng có tuổi thọ ngắn mà hầu như không tốn kém.
Dominic Cronin

65
String str = "223232-1.jpg"
int index = str.IndexOf('-');
if(index > 0) {
    return str.Substring(0, index)
}

ủng hộ vì tôi cần biết chỉ số của dấu phân cách
Piero Alberto.

3
Đây thực sự là câu trả lời giống như Fredou đã đưa ra (hiện là câu trả lời hàng đầu) ngoại trừ việc nó bỏ qua việc xử lý trường hợp không tìm thấy kết quả phù hợp nào.
Dominic Cronin

7

Mọi thứ đã tiến triển hơn một chút kể từ khi chủ đề này bắt đầu.

Bây giờ, bạn có thể sử dụng

string.Concat(s.TakeWhile((c) => c != '-'));

Làm thế nào để điều này so sánh hiệu suất khôn ngoan với sự kết hợp IndexOf và Chuỗi con rõ ràng? Tôi giả sử rằng nó đang nối mỗi ký tự vào một StringBuilder, và sau đó tạo ra một chuỗi ở cuối. Ngoài ra còn có một vài lệnh gọi hàm được trộn lẫn vào. Sẽ thật tuyệt nếu Chuỗi con có thể chỉ cần lấy -1 làm đối số "độ dài" có nghĩa là "cuối chuỗi".
nghiền nát

1
Nó kém hơn cho hiệu quả. Như bạn nói, nó sử dụng trình tạo chuỗi và sau khi kiểm tra mã sẽ gọi ToString trên mỗi ký tự. Sẽ rõ ràng hơn nếu bạn đang tìm kiếm nhiều hơn một ký tự, vì bạn có thể viết lại lambda một cách dễ dàng.
Anthony Wieser

5

Một cách để làm điều này là sử dụng String.Substringcùng với String.IndexOf:

int index = str.IndexOf('-');
string sub;
if (index >= 0)
{
    sub = str.Substring(0, index);
}
else
{
    sub = ... // handle strings without the dash
}

Bắt đầu từ vị trí 0, trả về tất cả văn bản, nhưng không bao gồm, dấu gạch ngang.


nếu index <= 0, bạn chỉ nên trả về string.empty.
Không hoàn lại tiền Không trả lại

5
@NRNR: nếu bạn nói vậy. OP biết các yêu cầu kinh doanh, không phải bạn hoặc I.
Michael Petrotta

0

Dựa trên câu trả lời của BrainCore:

    int index = 0;   
    str = "223232-1.jpg";

    //Assuming we trust str isn't null 
    if (str.Contains('-') == "true")
    {
      int index = str.IndexOf('-');
    }

    if(index > 0) {
        return str.Substring(0, index);
    }
    else {
       return str;
    }

0

Bạn có thể sử dụng biểu thức chính quy cho mục đích này, nhưng bạn nên tránh thêm ngoại lệ khi chuỗi nhập không khớp với biểu thức chính quy.

Đầu tiên để tránh phải đau đầu thêm khi thoát đến mẫu regex - chúng ta chỉ có thể sử dụng hàm cho mục đích đó:

String reStrEnding = Regex.Escape("-");

Tôi biết rằng điều này không làm bất cứ điều gì - như "-" giống như Regex.Escape("=") == "=", nhưng nó sẽ tạo ra sự khác biệt, ví dụ nếu ký tự là @"\".

Sau đó, chúng ta cần so khớp từ cầu xin của chuỗi thành kết thúc chuỗi hoặc thay thế nếu không tìm thấy kết thúc - sau đó không khớp với nhau. (Chuỗi trống)

Regex re = new Regex("^(.*?)" + reStrEnding);

Nếu ứng dụng của bạn là quan trọng về hiệu suất - thì hãy tách dòng cho Regex mới, nếu không - bạn có thể có mọi thứ trong một dòng.

Và cuối cùng đối sánh với chuỗi và trích xuất mẫu phù hợp:

String matched = re.Match(str).Groups[1].ToString();

Và sau đó, bạn có thể viết một hàm riêng biệt, giống như nó đã được thực hiện trong một câu trả lời khác, hoặc viết hàm lambda nội tuyến. Tôi đã viết bây giờ bằng cách sử dụng cả hai ký hiệu - hàm lambda nội tuyến (không cho phép tham số mặc định) hoặc lệnh gọi hàm riêng biệt.

using System;
using System.Text.RegularExpressions;

static class Helper
{
    public static string GetUntilOrEmpty(this string text, string stopAt = "-")
    {
        return new Regex("^(.*?)" + Regex.Escape(stopAt)).Match(text).Groups[1].Value;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Regex re = new Regex("^(.*?)-");
        Func<String, String> untilSlash = (s) => { return re.Match(s).Groups[1].ToString(); };

        Console.WriteLine(untilSlash("223232-1.jpg"));
        Console.WriteLine(untilSlash("443-2.jpg"));
        Console.WriteLine(untilSlash("34443553-5.jpg"));
        Console.WriteLine(untilSlash("noEnding(will result in empty string)"));
        Console.WriteLine(untilSlash(""));
        // Throws exception: Console.WriteLine(untilSlash(null));

        Console.WriteLine("443-2.jpg".GetUntilOrEmpty());
    }
}

Btw - thay đổi mẫu regex thành "^(.*?)(-|$)"sẽ cho phép chọn hoặc cho đến khi "-"mẫu hoặc nếu không tìm thấy mẫu - chọn mọi thứ cho đến khi kết thúc chuỗi.


0

Cách LINQy

String.Concat ("223232-1.jpg" .TakeWhile (c => c! = '-'))

(Nhưng, bạn cần phải kiểm tra null;)

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.