Bagaimana cara mengganti beberapa spasi dengan satu spasi di C #?

440

Bagaimana saya bisa mengganti banyak spasi dalam string dengan hanya satu spasi di C #?

Contoh:

1 2 3  4    5

akan menjadi:

1 2 3 4 5
Pokus
sumber
1
mesin negara dapat dengan mudah melakukannya, tetapi mungkin berlebihan jika Anda hanya perlu menghapus spasi
Adrian
Saya telah menambahkan patokan pada berbagai cara untuk melakukan ini dalam pertanyaan duplikat stackoverflow.com/a/37592018/582061 . Regex bukan cara tercepat untuk melakukan ini.
Stian Standahl

Jawaban:

469
string sentence = "This is a sentence with multiple    spaces";
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);     
sentence = regex.Replace(sentence, " ");
Patrick Desjardins
sumber
2
Saya telah menyalin dan menempelnya dan berfungsi. Saya benar-benar tidak suka REgex tetapi kali ini menyelamatkan hidup saya.
Pokus
9
@Craig komentar sudah cukup, IMO. // Blok ini menggantikan beberapa spasi dengan satu ... :)
paulwhit
6
Sungguh, RegEx berlebihan untuk ini.
Joel Coehoorn
11
@ Joel: Tidak setuju. Saya sebenarnya yakin bahwa cara ini lebih efisien daripada milik Anda untuk string yang cukup besar dan dapat dilakukan dalam satu baris. Di mana berlebihannya?
Konrad Rudolph
24
@Oscar Joel's code bukan loop sederhana melalui semua karakter! Ini adalah loop bersarang tersembunyi yang memiliki kasus terburuk kuadratik. Ekspresi reguler ini, sebaliknya, adalah linier, hanya membangun satu string (= mengurangi biaya alokasi secara drastis dibandingkan dengan kode Joel) dan lebih jauh lagi mesin dapat mengoptimalkannya (jujur ​​saja, saya ragu. NET regex adalah cukup pintar untuk ini tetapi secara teori ungkapan reguler ini dapat diimplementasikan dengan sangat murah sehingga tidak lucu lagi; hanya membutuhkan DFA dengan tiga negara, masing-masing satu transisi, dan tidak ada informasi tambahan).
Konrad Rudolph
624

Saya suka menggunakan:

myString = Regex.Replace(myString, @"\s+", " ");

Karena itu akan menangkap run dari segala jenis spasi putih (misalnya tab, baris baru, dll) dan menggantinya dengan satu spasi.

Mat
sumber
43
Modifikasi sedikit: Regex.Replace (sumber, @ "(\ s) \ s +", "$ 1"); Ini akan mengembalikan tipe spasi putih pertama yang ditemukan. Jadi jika Anda memiliki 5 tab, itu akan mengembalikan satu tab. Memetikan seseorang lebih suka ini.
FB ten Kate
@radistao Tautan Anda untuk penggantian string Javascript, bukan untuk C #.
Shiva
1
@Shiva, / \ s + s + / adalah pernyataan regex POSIX standar dan dapat dikonversi / digunakan dalam bahasa apa pun menggunakan sintaksis sendiri
radistao
4
Dalam semangat solusi @ FBtenKate: Regex.Replace (sumber, @ "(\ s) \ 1+", "$ 1"); akan mengganti beberapa karakter berurutan yang identik dengan satu karakter.
François Beaune
1
untuk menghapus spasi putih depan dan akhir, Anda harus menggunakan fungsi Trim () dengan ini ,, seperti var myString = Regex.Replace (myString, @ "\ s +", "") .Trim ();
Harish Nayak
50
string xyz = "1   2   3   4   5";
xyz = string.Join( " ", xyz.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ));
tvanfosson
sumber
6
Ini lebih mudah dibaca daripada regex, saya lebih suka itu karena saya tidak perlu belajar beberapa sintaks lainnya
Michael Bahig
9
Saya menyukainya karena tidak perlu Regex
AleX_
3
Ini tidak efisien untuk string besar.
DarcyThomas
3
Ini juga menghilangkan ruang depan dan belakang.
Matzi
1
Saya lebih suka jawaban ini juga. Mentor lama saya dulu mengatakan "kapan saja Anda memiliki masalah, Anda pikir Anda perlu Regex untuk menyelesaikannya, yah ... sekarang Anda punya dua masalah" <wink>
William Madonna Jr
38

Saya pikir jawaban Matt adalah yang terbaik, tetapi saya tidak yakin itu benar. Jika Anda ingin mengganti baris baru, Anda harus menggunakan:

myString = Regex.Replace(myString, @"\s+", " ", RegexOptions.Multiline);
Brenda Bell
sumber
4
RegexOptions.Multiline mengubah arti ^ dan $ sehingga cocok dengan awal dan akhir setiap baris ($ = \ n), bukan seluruh string multi-line. Karena \ s setara dengan [\ f \ n \ r \ t \ v] baris baru harus diganti bahkan jika opsi Multiline tidak aktif.
SushiGuy
1
Jawaban Matt sudah mencakup ini. Saya 'yakin' 30 orang baru saja menutup mata memilih jawaban ini :)
123iamking
26

Pendekatan lain yang menggunakan LINQ:

 var list = str.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
 str = string.Join(" ", list);
cuongle
sumber
23

Jauh lebih sederhana dari semua itu:

while(str.Contains("  ")) str = str.Replace("  ", " ");
Joel Coehoorn
sumber
23
Ini akan jauh lebih efisien daripada regex "{2,}" jika string berisi urutan 3 ruang atau lebih.
Jan Goyvaerts
2
@ JanGoyvaerts: Bahkan dengan 10 spasi, regex lebih lambat ketika saya melakukan tes cepat dan kotor. Yang sedang berkata, hanya membutuhkan satu substring raksasa penuh ruang untuk benar-benar membunuh kinerja dari loop sementara. Untuk keadilan, saya menggunakan saya menggunakan RegexOptions. Dikompilasi, bukan Regex yang lebih lambat. Ganti.
Brian
5
RegexOptions.Compiled menambahkan banyak overhead yang mengkompilasi regex ke IL. Jangan menggunakannya kecuali aplikasi Anda akan menggunakan regex cukup sering atau pada string yang cukup besar sehingga peningkatan kecepatan pencocokan mengimbangi penurunan kecepatan kompilasi.
Jan Goyvaerts
Ini adalah contoh kode tidak efisien yang ekstrem. LOL.
pcbabu
1
@ pcbabu Tidak seburuk yang terlihat pada banyak kasus. The Replace()Metode akan menangani semua kejadian dari dua ruang di suatu string, jadi kita tidak looping (dan re-mengalokasikan seluruh string) untuk setiap contoh dari ruang dipasangkan dalam string. Satu alokasi baru akan menangani semuanya. Kami hanya menjalankan kembali loop ketika ada 3 ruang atau lebih secara bersamaan, yang kemungkinan akan lebih jarang terjadi pada banyak sumber input. Jika Anda bisa menunjukkannya menjadi masalah bagi data Anda, maka tulis mesin negara untuk mendorong karakter demi karakter ke pembuat string baru.
Joel Coehoorn
21

Regex bisa agak lambat bahkan dengan tugas-tugas sederhana. Ini menciptakan metode ekstensi yang dapat digunakan dari apa pun string.

    public static class StringExtension
    {
        public static String ReduceWhitespace(this String value)
        {
            var newString = new StringBuilder();
            bool previousIsWhitespace = false;
            for (int i = 0; i < value.Length; i++)
            {
                if (Char.IsWhiteSpace(value[i]))
                {
                    if (previousIsWhitespace)
                    {
                        continue;
                    }

                    previousIsWhitespace = true;
                }
                else
                {
                    previousIsWhitespace = false;
                }

                newString.Append(value[i]);
            }

            return newString.ToString();
        }
    }

Ini akan digunakan seperti itu:

string testValue = "This contains     too          much  whitespace."
testValue = testValue.ReduceWhitespace();
// testValue = "This contains too much whitespace."
ScubaSteve
sumber
15
myString = Regex.Replace(myString, " {2,}", " ");
Jan Goyvaerts
sumber
11

Bagi mereka yang tidak suka Regex, berikut adalah metode yang menggunakan StringBuilder:

    public static string FilterWhiteSpaces(string input)
    {
        if (input == null)
            return string.Empty;

        StringBuilder stringBuilder = new StringBuilder(input.Length);
        for (int i = 0; i < input.Length; i++)
        {
            char c = input[i];
            if (i == 0 || c != ' ' || (c == ' ' && input[i - 1] != ' '))
                stringBuilder.Append(c);
        }
        return stringBuilder.ToString();
    }

Dalam pengujian saya, metode ini rata-rata 16 kali lebih cepat dengan set string berukuran kecil hingga sedang yang sangat besar, dibandingkan dengan Regex yang dikompilasi statis. Dibandingkan dengan Regex yang tidak dikompilasi atau non-statis, ini harus lebih cepat.

Perlu diingat, bahwa itu tidak menghilangkan ruang depan atau belakang, hanya beberapa kejadian seperti itu.

Nolonar
sumber
Jika Anda ingin memeriksa apakah karakter tersebut adalah spasi, dan bukan hanya spasi lihat jawaban saya di bawah ini .
Menuai
8

Anda bisa melakukan ini dalam satu solusi!

string s = "welcome to  london";
s.Replace(" ", "()").Replace(")(", "").Replace("()", " ");

Anda dapat memilih tanda kurung lain (atau bahkan karakter lain) jika suka.

ravish.hacker
sumber
1
Anda harus memastikan string Anda tidak memiliki "()" atau ") (" di dalamnya. Atau "wel()come to london)("menjadi "wel come to london". Anda bisa mencoba menggunakan banyak tanda kurung. Jadi gunakan ((((()))))sebagai ganti ()dan )))))(((((alih-alih )(. Itu masih akan berfungsi. Namun, jika string berisi ((((()))))atau )))))(((((, ini akan gagal
nmit026
7

Ini adalah versi yang lebih pendek, yang seharusnya hanya digunakan jika Anda hanya melakukan ini sekali saja, karena ini akan membuat instance Regexkelas baru setiap kali dipanggil.

temp = new Regex(" {2,}").Replace(temp, " "); 

Jika Anda tidak terlalu mengenal ekspresi reguler, inilah penjelasan singkat:

The {2,}membuat regex mencari karakter yang mendahuluinya, dan menemukan substring antara 2 dan kali tidak terbatas.
The .Replace(temp, " ")menggantikan semua pertandingan di temp string dengan spasi.

Jika Anda ingin menggunakan ini berkali-kali, ini adalah opsi yang lebih baik, karena ini menciptakan regex IL pada waktu kompilasi:

Regex singleSpacify = new Regex(" {2,}", RegexOptions.Compiled);
temp = singleSpacify.Replace(temp, " ");
seseorang
sumber
7

no Regex, no Linq ... menghapus spasi awal dan akhir serta mengurangi beberapa segmen spasi yang disematkan menjadi satu spasi

string myString = "   0 1 2  3   4               5  ";
myString = string.Join(" ", myString.Split(new char[] { ' ' }, 
StringSplitOptions.RemoveEmptyEntries));

hasil: "0 1 2 3 4 5"

Stephen du Buis
sumber
1
Kata hati-hati: Penggunaan split, meskipun sangat sederhana untuk dipahami, dapat memiliki dampak kinerja yang sangat negatif. Karena banyak string dapat dibuat, Anda harus mengawasi penggunaan memori Anda jika Anda menangani string besar dengan metode ini.
Pac0
5

Menghemat jawaban lain, per Joel, dan semoga sedikit membaik saat aku mulai:

Anda dapat melakukan ini dengan Regex.Replace():

string s = Regex.Replace (
    "   1  2    4 5", 
    @"[ ]{2,}", 
    " "
    );

Atau dengan String.Split():

static class StringExtensions
{
    public static string Join(this IList<string> value, string separator)
    {
        return string.Join(separator, value.ToArray());
    }
}

//...

string s = "     1  2    4 5".Split (
    " ".ToCharArray(), 
    StringSplitOptions.RemoveEmptyEntries
    ).Join (" ");
Jay Bazuzi
sumber
3

Saya baru saja menulis yang baru Joinsaya suka, jadi saya pikir saya akan menjawab kembali, dengan itu:

public static string Join<T>(this IEnumerable<T> source, string separator)
{
    return string.Join(separator, source.Select(e => e.ToString()).ToArray());
}

Salah satu hal keren tentang ini adalah ia bekerja dengan koleksi yang bukan string, dengan memanggil ToString () pada elemen. Penggunaannya masih sama:

//...

string s = "     1  2    4 5".Split (
    " ".ToCharArray(), 
    StringSplitOptions.RemoveEmptyEntries
    ).Join (" ");
Jay Bazuzi
sumber
2
mengapa membuat metode ekstensi? mengapa tidak menggunakan string.Join ()?
Eric Schoonover
3
      // Mysample string
            string str ="hi you           are          a demo";

            //Split the words based on white sapce
            var demo= str .Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));

            //Join the values back and add a single space in between
                    str = string.Join(" ", demo);

//output: string str ="hi you are a demo";
JIYAUL MUSTAPHA
sumber
2

Saya tahu ini cukup tua, tetapi berlari melintasi ini sambil mencoba untuk mencapai hal yang hampir sama. Menemukan solusi ini di RegEx Buddy. Pola ini akan menggantikan semua ruang ganda dengan ruang tunggal dan juga memangkas ruang depan dan belakang.

pattern: (?m:^ +| +$|( ){2,})
replacement: $1

Agak sulit dibaca karena kita berhadapan dengan ruang kosong, jadi ini dia lagi dengan "spasi" diganti dengan "_".

pattern: (?m:^_+|_+$|(_){2,})  <-- don't use this, just for illustration.

Konstruk "(? M:" memungkinkan opsi "multi-line". Saya biasanya ingin memasukkan opsi apa pun yang saya dapat di dalam pola itu sendiri sehingga lebih mandiri.

Paul Easter
sumber
2

Banyak jawaban memberikan output yang tepat tetapi bagi mereka yang mencari kinerja terbaik, saya memang meningkatkan jawaban Nolanar (yang merupakan jawaban terbaik untuk kinerja) sekitar 10%.

public static string MergeSpaces(this string str)
{

    if (str == null)
    {
        return null;
    }
    else
    {
        StringBuilder stringBuilder = new StringBuilder(str.Length);

        int i = 0;
        foreach (char c in str)
        {
            if (c != ' ' || i == 0 || str[i - 1] != ' ')
                stringBuilder.Append(c);
            i++;
        }
        return stringBuilder.ToString();
    }

}
The_Black_Smurf
sumber
1

Saya dapat menghapus spasi putih dengan ini

while word.contains("  ")  //double space
   word = word.Replace("  "," "); //replace double space by single space.
word = word.trim(); //to remove single whitespces from start & end.
Pelajar1947
sumber
ya tetapi Anda hanya akan mengganti dua spasi putih dengan satu. Ini tidak akan membantu jumlah ruang X
MGot90
1
Loop Sementara itu akan menangani semua ruang ganda yang akan dihapus.
Learner1947
1

Gunakan pola regex

    [ ]+    #only space

   var text = Regex.Replace(inputString, @"[ ]+", " ");
M.Hassan
sumber
1

coba metode ini

private string removeNestedWhitespaces(char[] st)
{
    StringBuilder sb = new StringBuilder();
    int indx = 0, length = st.Length;
    while (indx < length)
    {
        sb.Append(st[indx]);
        indx++;
        while (indx < length && st[indx] == ' ')
            indx++;
        if(sb.Length > 1  && sb[0] != ' ')
            sb.Append(' ');
    }
    return sb.ToString();
}

gunakan seperti ini:

string test = removeNestedWhitespaces("1 2 3  4    5".toCharArray());
Ahmed Aljaff
sumber
Ini akan menghapus spasi tambahan
The_Black_Smurf
maaf atas kesalahannya, saya memperbaiki kodenya, sekarang ini berfungsi seperti yang diharapkan string yang diuji: "1 2 3 4 9" string hasil: "1 2 3 4 9"
Ahmed Aljaff
1

Berikut ini sedikit modifikasi pada jawaban asli Nolonar .

Memeriksa apakah karakternya bukan hanya spasi, tetapi spasi apa pun, gunakan ini:

Ini akan menggantikan beberapa karakter spasi putih dengan satu spasi.

public static string FilterWhiteSpaces(string input)
{
    if (input == null)
        return string.Empty;

    var stringBuilder = new StringBuilder(input.Length);
    for (int i = 0; i < input.Length; i++)
    {
        char c = input[i];
        if (i == 0 || !char.IsWhiteSpace(c) || (char.IsWhiteSpace(c) && 
            !char.IsWhiteSpace(strValue[i - 1])))
            stringBuilder.Append(c);
    }
    return stringBuilder.ToString();
}
Menuai
sumber
0

Skool lama:

string oldText = "   1 2  3   4    5     ";
string newText = oldText
                    .Replace("  ", " " + (char)22 )
                    .Replace( (char)22 + " ", "" )
                    .Replace( (char)22 + "", "" );

Assert.That( newText, Is.EqualTo( " 1 2 3 4 5 " ) );
suatu hari nanti
sumber
0

Tanpa menggunakan ekspresi reguler:

while (myString.IndexOf("  ", StringComparison.CurrentCulture) != -1)
{
    myString = myString.Replace("  ", " ");
}

OK untuk digunakan pada string pendek, tetapi akan berkinerja buruk pada string panjang dengan banyak ruang.

Tom Gullen
sumber
0

Campuran StringBuilder dan Enumerable.Aggregate () sebagai metode ekstensi untuk string:

using System;
using System.Linq;
using System.Text;

public static class StringExtension
{
    public static string StripSpaces(this string s)
    {
        return s.Aggregate(new StringBuilder(), (acc, c) =>
        {
            if (c != ' ' || acc.Length > 0 && acc[acc.Length-1] != ' ')
                acc.Append(c);

            return acc;
        }).ToString();
    }

    public static void Main()
    {
        Console.WriteLine("\"" + StringExtension.StripSpaces("1   Hello       World  2   ") + "\"");
    }
}

Memasukkan:

"1   Hello       World  2   "

Keluaran:

"1 Hello World 2 "
Patrick Artner
sumber