.NET'te bir dizeden aksan işaretleri (aksanları) nasıl kaldırabilirim?


433

Ben Fransızca Kanada bazı dizeleri dönüştürmek için çalışıyorum ve temelde, mektup tutarken harfleri Fransızca aksan işaretleri çıkarmak istiyorum. (Örn dönüştürme éiçin e, bu yüzden crème brûléeolacaktı creme brulee)

Bunu başarmanın en iyi yolu nedir?


14
Uyarı: Bu yaklaşım bazı özel durumlarda işe yarayabilir, ancak genel olarak aksan işaretlerini kaldıramazsınız. Bazı durumlarda ve bazı dillerde bu metnin anlamını değiştirebilir. Bunu neden yapmak istediğini söylemiyorsun; eğer dizeleri karşılaştırmak veya aramak uğruna, bunun için unicode uyumlu bir kütüphane kullanarak büyük olasılıkla daha iyi olursunuz.
JacquesB

1
Tekniklerin çoğu bu Unicode normalleştirme güvenmek elde etmek için, standart açıklayan bu belge okumak için yararlı olabilir: unicode.org/reports/tr15
LuddyPants

Azure ekibinin bu sorunu çözdüğünü düşünüyorum, "Mémo de la réunion.pdf" adlı bir dosya yüklemeye çalıştım ve işlem başarılı oldu.
Rady

Yanıtlar:


532

Bu yöntemi kullanmadım, ancak Michael Kaplan, blog yazısında (kafa karıştırıcı bir başlıkla) aksanları sıyırma hakkında konuşan bir yöntem açıklıyor: Sıyırma ilginç bir iştir (aka anlamsız, aka Tüm Mn karakterleri hakkında boşluk bırakmayan ancak bazıları diğerlerinden daha boşluk bırakmayan)

static string RemoveDiacritics(string text) 
{
    var normalizedString = text.Normalize(NormalizationForm.FormD);
    var stringBuilder = new StringBuilder();

    foreach (var c in normalizedString)
    {
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}

Bu onun önceki yazı bir takip olduğunu unutmayın: Soyma aksan ....

Yaklaşım , giriş dizesini kurucu gliflere ayırmak için String.Normalize kullanır (temel olarak "temel" karakterleri aksan işaretlerinden ayırır) ve ardından sonucu tarar ve yalnızca temel karakterleri korur. Bu sadece biraz karmaşık, ama gerçekten karmaşık bir soruna bakıyorsunuz.

Tabii ki, kendinizi Fransızca ile sınırlıyorsanız, muhtemelen @David Dibben tarafından önerildiği gibi bir C ++ std :: dizesindeki aksan ve tilde nasıl kaldırılır konusundaki basit tablo tabanlı yaklaşımdan kurtulabilirsiniz.


32
Bu yanlış. Almanca karakterler ä ve ö ve ü aeue ve oe olarak latine edilmiş ve au olarak değil ...
Stefan Steiger

20
Ayrıca, Lehçe harf ł yok sayılır.
Zbigniew Wiadro

4
Ayrıca Norse ø önemsenmez
Richard de Wit

28
@StefanSteiger Bildiğiniz gibi, Çekçe'de áč letters gibi, aceu'ya genellikle "latinize" ettiğimiz harfler var, farklı görünse ve "hrábě" / hra: bje /, "hrabě" / hrabje /, ve "hrabe" / hrabe /. Bana göre, aksanların silinmesi, mektubun fonetiğine veya tarihine bağlı olarak tamamen grafiksel bir konudur. Ä ö ü gibi harfler, temel harflere bir üst simge "e" ekleyerek oluşturulmuştur, böylece "ae" ayrışması tarihsel olarak mantıklıdır. Hedefe bağlıdır - grafik işaretleri kaldırmak veya harfi ASCII karakterlerine ayırmak.
IllidanS4, Monica'nın

10
Bu işlev dile agnostiktir. Dizenin Almanca mı yoksa başka bir dilde mi olduğunu bilmiyor. Almanca bir metinde ö yerine oe yazmanın doğru olduğunu düşünürsek, ancak bunu Türkçe ile yapmanın bir anlamı olmazsa, dili tespit etmeden bu sorunun gerçekten çözülemez olduğunu göreceğiz.
thorn̈

163

bu benim için hile yaptı ...

string accentedStr;
byte[] tempBytes;
tempBytes = System.Text.Encoding.GetEncoding("ISO-8859-8").GetBytes(accentedStr);
string asciiStr = System.Text.Encoding.UTF8.GetString(tempBytes);

hızlı & kısa!


9
Bu gördüğüm en iyi yöntem.
Cleiton

2
Bu çözümü beğendim ve Windows Mağazası Uygulamaları için iyi çalışıyor. Ancak, ISO-8859-8 kodlaması mevcut görünmediği için Windows Phone Uygulamaları için çalışmaz. Bunun yerine kullanılabilecek başka bir kodlama var mı?
Philip Colmer

2
Bu, en yaygın karakterler için işe yarayacaktır, ancak « »ve (tek bir karakter olarak) gibi birçok özel karakter , kabul edilen çözümde geçerli olmayan süreçte değişecektir.
The_Black_Smurf

7
Bunun Linux'ta .NET Core'da çalışmadığını unutmayın:System.ArgumentException: 'ISO-8859-8' is not a supported encoding name.
EM0

2
.NET Core kullanıyorsanız, System.Text.Encoding.CodePagesnuget'ten yükleyin , ardından sağlayıcıyı kaydetmek için bunu arayın: Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);- bunu yaptıktan sonra ISO-8859-8
SpaceBison

32

Birisi ilgilenirse, benzer bir şey arıyordum ve aşağıdakileri yazmayı bitirdim:

public static string NormalizeStringForUrl(string name)
{
    String normalizedString = name.Normalize(NormalizationForm.FormD);
    StringBuilder stringBuilder = new StringBuilder();

    foreach (char c in normalizedString)
    {
        switch (CharUnicodeInfo.GetUnicodeCategory(c))
        {
            case UnicodeCategory.LowercaseLetter:
            case UnicodeCategory.UppercaseLetter:
            case UnicodeCategory.DecimalDigitNumber:
                stringBuilder.Append(c);
                break;
            case UnicodeCategory.SpaceSeparator:
            case UnicodeCategory.ConnectorPunctuation:
            case UnicodeCategory.DashPunctuation:
                stringBuilder.Append('_');
                break;
        }
    }
    string result = stringBuilder.ToString();
    return String.Join("_", result.Split(new char[] { '_' }
        , StringSplitOptions.RemoveEmptyEntries)); // remove duplicate underscores
}

9
Bellek ayırma ek yükünü en aza indirmek için StringBuilder arabelleğini adla yeniden konumlandırmalısınız. Sıralı yinelenen _'i kaldırmak için son Bölme / Birleştirme çağrısı ilginçtir. Belki de bunları döngüye eklemekten kaçınmalıyız. Önceki karakterin _ olması için bir bayrak ayarlayın ve doğruysa bir bayrak yaymayın.
ıdisposable

2 gerçekten iyi puan, kodun bu bölümüne geri dönmek için zaman alırsam yeniden yazacağım :)
Luk

Güzel. IDisposables yorumuna ek olarak, muhtemelen c < 128UTF karakterlerini almadığımızdan emin olmak için kontrol etmeliyiz , buraya bakın .
Christian Gollhardt

1
Ya da muhtemelen daha verimli c < 123. bkz
ASCI

hala ø gibi karakterlerle çalışmıyor
juanora

27

Tüm büyük unicode karakterleri dönüştüren bir şeye ihtiyacım vardı ve oylanan cevap birkaç dışarı çıktı, bu yüzden convert_accented_characters($str)kolayca özelleştirilebilir bir kod # CodeIgniter's sürümü oluşturdum :

using System;
using System.Text;
using System.Collections.Generic;

public static class Strings
{
    static Dictionary<string, string> foreign_characters = new Dictionary<string, string>
    {
        { "äæǽ", "ae" },
        { "öœ", "oe" },
        { "ü", "ue" },
        { "Ä", "Ae" },
        { "Ü", "Ue" },
        { "Ö", "Oe" },
        { "ÀÁÂÃÄÅǺĀĂĄǍΑΆẢẠẦẪẨẬẰẮẴẲẶА", "A" },
        { "àáâãåǻāăąǎªαάảạầấẫẩậằắẵẳặа", "a" },
        { "Б", "B" },
        { "б", "b" },
        { "ÇĆĈĊČ", "C" },
        { "çćĉċč", "c" },
        { "Д", "D" },
        { "д", "d" },
        { "ÐĎĐΔ", "Dj" },
        { "ðďđδ", "dj" },
        { "ÈÉÊËĒĔĖĘĚΕΈẼẺẸỀẾỄỂỆЕЭ", "E" },
        { "èéêëēĕėęěέεẽẻẹềếễểệеэ", "e" },
        { "Ф", "F" },
        { "ф", "f" },
        { "ĜĞĠĢΓГҐ", "G" },
        { "ĝğġģγгґ", "g" },
        { "ĤĦ", "H" },
        { "ĥħ", "h" },
        { "ÌÍÎÏĨĪĬǏĮİΗΉΊΙΪỈỊИЫ", "I" },
        { "ìíîïĩīĭǐįıηήίιϊỉịиыї", "i" },
        { "Ĵ", "J" },
        { "ĵ", "j" },
        { "ĶΚК", "K" },
        { "ķκк", "k" },
        { "ĹĻĽĿŁΛЛ", "L" },
        { "ĺļľŀłλл", "l" },
        { "М", "M" },
        { "м", "m" },
        { "ÑŃŅŇΝН", "N" },
        { "ñńņňʼnνн", "n" },
        { "ÒÓÔÕŌŎǑŐƠØǾΟΌΩΏỎỌỒỐỖỔỘỜỚỠỞỢО", "O" },
        { "òóôõōŏǒőơøǿºοόωώỏọồốỗổộờớỡởợо", "o" },
        { "П", "P" },
        { "п", "p" },
        { "ŔŖŘΡР", "R" },
        { "ŕŗřρр", "r" },
        { "ŚŜŞȘŠΣС", "S" },
        { "śŝşșšſσςс", "s" },
        { "ȚŢŤŦτТ", "T" },
        { "țţťŧт", "t" },
        { "ÙÚÛŨŪŬŮŰŲƯǓǕǗǙǛŨỦỤỪỨỮỬỰУ", "U" },
        { "ùúûũūŭůűųưǔǖǘǚǜυύϋủụừứữửựу", "u" },
        { "ÝŸŶΥΎΫỲỸỶỴЙ", "Y" },
        { "ýÿŷỳỹỷỵй", "y" },
        { "В", "V" },
        { "в", "v" },
        { "Ŵ", "W" },
        { "ŵ", "w" },
        { "ŹŻŽΖЗ", "Z" },
        { "źżžζз", "z" },
        { "ÆǼ", "AE" },
        { "ß", "ss" },
        { "IJ", "IJ" },
        { "ij", "ij" },
        { "Œ", "OE" },
        { "ƒ", "f" },
        { "ξ", "ks" },
        { "π", "p" },
        { "β", "v" },
        { "μ", "m" },
        { "ψ", "ps" },
        { "Ё", "Yo" },
        { "ё", "yo" },
        { "Є", "Ye" },
        { "є", "ye" },
        { "Ї", "Yi" },
        { "Ж", "Zh" },
        { "ж", "zh" },
        { "Х", "Kh" },
        { "х", "kh" },
        { "Ц", "Ts" },
        { "ц", "ts" },
        { "Ч", "Ch" },
        { "ч", "ch" },
        { "Ш", "Sh" },
        { "ш", "sh" },
        { "Щ", "Shch" },
        { "щ", "shch" },
        { "ЪъЬь", "" },
        { "Ю", "Yu" },
        { "ю", "yu" },
        { "Я", "Ya" },
        { "я", "ya" },
    };

    public static char RemoveDiacritics(this char c){
        foreach(KeyValuePair<string, string> entry in foreign_characters)
        {
            if(entry.Key.IndexOf (c) != -1)
            {
                return entry.Value[0];
            }
        }
        return c;
    }

    public static string RemoveDiacritics(this string s) 
    {
        //StringBuilder sb = new StringBuilder ();
        string text = "";


        foreach (char c in s)
        {
            int len = text.Length;

            foreach(KeyValuePair<string, string> entry in foreign_characters)
            {
                if(entry.Key.IndexOf (c) != -1)
                {
                    text += entry.Value;
                    break;
                }
            }

            if (len == text.Length) {
                text += c;  
            }
        }
        return text;
    }
}

kullanım

// for strings
"crème brûlée".RemoveDiacritics (); // creme brulee

// for chars
"Ã"[0].RemoveDiacritics (); // A

5
Uygulamanız işi yapar, ancak üretim kodunda kullanılmadan önce geliştirilmelidir.
Pierre Arnaud


neden sadece bu değiştirmez if (entry.Key.IndexOf(c) != -1)içineif (entry.Key.Contains(c))
Pawel Cioch

Neden RemoveDiacritics (char c) döngüsünde yeniden kullanılmıyor, neden StringBuilder kullanılmıyor? Karmaşık sözlük ve çalışma çözümü için oy veriyorum, ancak kod çok daha basit olabilir
Pawel Cioch

1
Neden sadece çember kullanmak ve aramak { "äæǽ", "ae" }yerine çember atlama olduğunu anlamıyorum . Sözlüğün zaten sahip olduğu dizinin amacını tamamen yendin. { "ä", "ae" }, { "æ", "ae" }, { "ǽ", "ae" }if (foreign_characters.TryGetValue(...)) ...
Bacon Bits

15

Birinin ilgilenmesi durumunda, java eşdeğeri şöyledir:

import java.text.Normalizer;

public class MyClass
{
    public static String removeDiacritics(String input)
    {
        String nrml = Normalizer.normalize(input, Normalizer.Form.NFD);
        StringBuilder stripped = new StringBuilder();
        for (int i=0;i<nrml.length();++i)
        {
            if (Character.getType(nrml.charAt(i)) != Character.NON_SPACING_MARK)
            {
                stripped.append(nrml.charAt(i));
            }
        }
        return stripped.toString();
    }
}

3
soyulmuş + = nrml.charAt (i) yerine bir StringBuilder kullanın. Burada gizli O (n²) çalışma süreniz var.
Andreas Petersson

6
Bu ve diğer Java cevapları sadece bu iş parçacığı bir karışıklık vardır. Soru Java ile değil c # (.NET) hakkında!
suchoss

15

Sıklıkla burada bulduğum başka bir sürüme dayanan bir uzatma yöntemi kullanıyorum (bkz . C # (ascii) içindeki karakterleri değiştirme ) Hızlı bir açıklama:

  • Gibi D böler charactes oluşturulması için normalleştirilmesi è bir etmek e ve Aralıksız '
  • Bundan, nospacing karakterleri kaldırılır
  • Sonuç C formuna geri normalleştirilir (bunun gerekli olup olmadığından emin değilim)

Kod:

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

// namespace here
public static class Utility
{
    public static string RemoveDiacritics(this string str)
    {
        if (null == str) return null;
        var chars =
            from c in str.Normalize(NormalizationForm.FormD).ToCharArray()
            let uc = CharUnicodeInfo.GetUnicodeCategory(c)
            where uc != UnicodeCategory.NonSpacingMark
            select c;

        var cleanStr = new string(chars.ToArray()).Normalize(NormalizationForm.FormC);

        return cleanStr;
    }

    // or, alternatively
    public static string RemoveDiacritics2(this string str)
    {
        if (null == str) return null;
        var chars = str
            .Normalize(NormalizationForm.FormD)
            .ToCharArray()
            .Where(c=> CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
            .ToArray();

        return new string(chars).Normalize(NormalizationForm.FormC);
    }
}

9

Yunanca CodePage (ISO) bunu yapabilir

Bu kod sayfasıyla ilgili bilgiler System.Text.Encoding.GetEncodings(). Şurada bilgi edinin: https://msdn.microsoft.com/pt-br/library/system.text.encodinginfo.getencoding(v=vs.110).aspx

Yunanca (ISO) 28597 kod sayfasına ve iso- 8859-7 adına sahiptir .

Koda git ... \ o /

string text = "Você está numa situação lamentável";

string textEncode = System.Web.HttpUtility.UrlEncode(text, Encoding.GetEncoding("iso-8859-7"));
//result: "Voce+esta+numa+situacao+lamentavel"

string textDecode = System.Web.HttpUtility.UrlDecode(textEncode);
//result: "Voce esta numa situacao lamentavel"

Bu fonksiyonu yaz ...

public string RemoveAcentuation(string text)
{
    return
        System.Web.HttpUtility.UrlDecode(
            System.Web.HttpUtility.UrlEncode(
                text, Encoding.GetEncoding("iso-8859-7")));
}

... o Not Encoding.GetEncoding("iso-8859-7")eşdeğerdir Encoding.GetEncoding(28597)ilk isim ve Kodlama ikinci kod sayfası olduğu için.


3
Harika! Kısa ve verimli!
krlzlx

1
Harika şeyler. Test ettiğim neredeyse tüm karakterler geçti. ( äáčďěéíľľňôóřŕšťúůýž ÄÁČĎĚÉÍĽĽŇÔÓŘŔŠŤÚŮÝŽ ÖÜË łŁđĐ ţŢşŞçÇ øı). Sorunlar sadece ßədönüştürülmüş olarak bulundu ?, ancak bu tür istisnalar her zaman ayrı bir şekilde ele alınabilir. Bunu üretime sokmadan önce test, aksan harfleri içeren tüm Unicode alanlara karşı daha iyi yapılmalıdır.
miroxlav

5

Böyle bir soru çok fazla cevap alabilir ve yine de hiçbiri gereksinimlerimi karşılamıyor komik :) Çevresinde çok fazla dil var, diğerleri tam olarak bir agnostik çözüm AFAIK gerçekten mümkün değil, diğerleri FormC veya FormD'nin sorunları verdiğini belirtti.

Orijinal soru Fransızca ile ilgili olduğundan, en basit çalışma cevabı gerçekten

    public static string ConvertWesternEuropeanToASCII(this string str)
    {
        return Encoding.ASCII.GetString(Encoding.GetEncoding(1251).GetBytes(str));
    }

1251, giriş dilinin kodlama kodu ile değiştirilmelidir.

Ancak bu, yalnızca bir karakterin yerine bir karakterin yerini alır. Ben de girdi olarak Almanca ile çalıştığım için, manuel bir dönüştürme yaptım

    public static string LatinizeGermanCharacters(this string str)
    {
        StringBuilder sb = new StringBuilder(str.Length);
        foreach (char c in str)
        {
            switch (c)
            {
                case 'ä':
                    sb.Append("ae");
                    break;
                case 'ö':
                    sb.Append("oe");
                    break;
                case 'ü':
                    sb.Append("ue");
                    break;
                case 'Ä':
                    sb.Append("Ae");
                    break;
                case 'Ö':
                    sb.Append("Oe");
                    break;
                case 'Ü':
                    sb.Append("Ue");
                    break;
                case 'ß':
                    sb.Append("ss");
                    break;
                default:
                    sb.Append(c);
                    break;
            }
        }
        return sb.ToString();
    }

En iyi performansı vermeyebilir, ancak en azından okumak ve genişletmek çok kolaydır. Regex bir NO GO, herhangi bir char / string şeyden çok daha yavaştır.

Ayrıca alanı kaldırmak için çok basit bir yöntem var:

    public static string RemoveSpace(this string str)
    {
        return str.Replace(" ", string.Empty);
    }

Sonunda, yukarıdaki 3 uzantıların bir kombinasyonunu kullanıyorum:

    public static string LatinizeAndConvertToASCII(this string str, bool keepSpace = false)
    {
        str = str.LatinizeGermanCharacters().ConvertWesternEuropeanToASCII();            
        return keepSpace ? str : str.RemoveSpace();
    }

Ve başarılı bir şekilde geçen (kapsamlı olmayan) küçük bir birim testi.

    [TestMethod()]
    public void LatinizeAndConvertToASCIITest()
    {
        string europeanStr = "Bonjour ça va? C'est l'été! Ich möchte ä Ä á à â ê é è ë Ë É ï Ï î í ì ó ò ô ö Ö Ü ü ù ú û Û ý Ý ç Ç ñ Ñ";
        string expected = "Bonjourcava?C'estl'ete!IchmoechteaeAeaaaeeeeEEiIiiiooooeOeUeueuuuUyYcCnN";
        string actual = europeanStr.LatinizeAndConvertToASCII();
        Assert.AreEqual(expected, actual);
    }

4

Java'da bu iyi çalışıyor.

Temelde tüm aksanlı karakterleri, aksanlarını birleştiren, sonradan tasnif edilmiş meslektaşlarına dönüştürür. Şimdi aksanları ayırmak için bir normal ifade kullanabilirsiniz.

import java.text.Normalizer;
import java.util.regex.Pattern;

public String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); 
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}

Veya Java 7'de,"\\p{Block=CombiningDiacriticalMarks}"
Brent Faust

11
Soru özellikle .NET istediğinde neden bir Java çözümü yayınlasınız?
David

2
@David Bu soru, "java drop aksanları" için Google'da en popüler olanıdır. Buraya ait olduğunu söylememek, ama burada faydalı.
blubb

3

TL; DR - C # dize genişletme yöntemi

Ben dize anlamını korumak için en iyi çözüm de örnek gösterilmektedir ki, onları sıyırma yerine karakterleri dönüştürmek olduğunu düşünüyorum crème brûléeiçin crme brlevs. creme brulee.

Yukarıda Alexander'ın yorumunu kontrol ettim ve Lucene.Net kodunun Apache 2.0 lisanslı olduğunu gördüm, bu yüzden sınıfı basit bir dize uzantısı yöntemine dönüştürdüm. Bu şekilde kullanabilirsiniz:

var originalString = "crème brûlée";
var maxLength = originalString.Length; // limit output length as necessary
var foldedString = originalString.FoldToASCII(maxLength); 
// "creme brulee"

Bir StackOverflow cevap (30k izin lol ~ 139k karakter) göndermek için çok uzun bir özledim ve yazarları atfedilen :

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/// <summary>
/// This class converts alphabetic, numeric, and symbolic Unicode characters
/// which are not in the first 127 ASCII characters (the "Basic Latin" Unicode
/// block) into their ASCII equivalents, if one exists.
/// <para/>
/// Characters from the following Unicode blocks are converted; however, only
/// those characters with reasonable ASCII alternatives are converted:
/// 
/// <ul>
///   <item><description>C1 Controls and Latin-1 Supplement: <a href="http://www.unicode.org/charts/PDF/U0080.pdf">http://www.unicode.org/charts/PDF/U0080.pdf</a></description></item>
///   <item><description>Latin Extended-A: <a href="http://www.unicode.org/charts/PDF/U0100.pdf">http://www.unicode.org/charts/PDF/U0100.pdf</a></description></item>
///   <item><description>Latin Extended-B: <a href="http://www.unicode.org/charts/PDF/U0180.pdf">http://www.unicode.org/charts/PDF/U0180.pdf</a></description></item>
///   <item><description>Latin Extended Additional: <a href="http://www.unicode.org/charts/PDF/U1E00.pdf">http://www.unicode.org/charts/PDF/U1E00.pdf</a></description></item>
///   <item><description>Latin Extended-C: <a href="http://www.unicode.org/charts/PDF/U2C60.pdf">http://www.unicode.org/charts/PDF/U2C60.pdf</a></description></item>
///   <item><description>Latin Extended-D: <a href="http://www.unicode.org/charts/PDF/UA720.pdf">http://www.unicode.org/charts/PDF/UA720.pdf</a></description></item>
///   <item><description>IPA Extensions: <a href="http://www.unicode.org/charts/PDF/U0250.pdf">http://www.unicode.org/charts/PDF/U0250.pdf</a></description></item>
///   <item><description>Phonetic Extensions: <a href="http://www.unicode.org/charts/PDF/U1D00.pdf">http://www.unicode.org/charts/PDF/U1D00.pdf</a></description></item>
///   <item><description>Phonetic Extensions Supplement: <a href="http://www.unicode.org/charts/PDF/U1D80.pdf">http://www.unicode.org/charts/PDF/U1D80.pdf</a></description></item>
///   <item><description>General Punctuation: <a href="http://www.unicode.org/charts/PDF/U2000.pdf">http://www.unicode.org/charts/PDF/U2000.pdf</a></description></item>
///   <item><description>Superscripts and Subscripts: <a href="http://www.unicode.org/charts/PDF/U2070.pdf">http://www.unicode.org/charts/PDF/U2070.pdf</a></description></item>
///   <item><description>Enclosed Alphanumerics: <a href="http://www.unicode.org/charts/PDF/U2460.pdf">http://www.unicode.org/charts/PDF/U2460.pdf</a></description></item>
///   <item><description>Dingbats: <a href="http://www.unicode.org/charts/PDF/U2700.pdf">http://www.unicode.org/charts/PDF/U2700.pdf</a></description></item>
///   <item><description>Supplemental Punctuation: <a href="http://www.unicode.org/charts/PDF/U2E00.pdf">http://www.unicode.org/charts/PDF/U2E00.pdf</a></description></item>
///   <item><description>Alphabetic Presentation Forms: <a href="http://www.unicode.org/charts/PDF/UFB00.pdf">http://www.unicode.org/charts/PDF/UFB00.pdf</a></description></item>
///   <item><description>Halfwidth and Fullwidth Forms: <a href="http://www.unicode.org/charts/PDF/UFF00.pdf">http://www.unicode.org/charts/PDF/UFF00.pdf</a></description></item>
/// </ul>
/// <para/>
/// See: <a href="http://en.wikipedia.org/wiki/Latin_characters_in_Unicode">http://en.wikipedia.org/wiki/Latin_characters_in_Unicode</a>
/// <para/>
/// For example, '&amp;agrave;' will be replaced by 'a'.
/// </summary>
public static partial class StringExtensions
{
    /// <summary>
    /// Converts characters above ASCII to their ASCII equivalents.  For example,
    /// accents are removed from accented characters. 
    /// </summary>
    /// <param name="input">     The string of characters to fold </param>
    /// <param name="length">    The length of the folded return string </param>
    /// <returns> length of output </returns>
    public static string FoldToASCII(this string input, int? length = null)
    {
        // See https://gist.github.com/andyraddatz/e6a396fb91856174d4e3f1bf2e10951c
    }
}

Umarım bir başkasına yardım eder, bulduğum en sağlam çözüm!


Uyarılar: 1) Konsept yerel ayara bağlıdır. Örneğin, "ä", "a" veya "aa" olabilir. 2) Yanlış adlandırılmış / yanlış tanımlanmış: Sonuç mutlaka C0 Denetimleri ve Temel Latin bloğundan gelmez. Yalnızca Latin harflerini ve bazı sembol varyantlarını "eşdeğerlerine" dönüştürür. (Tabii ki, daha sonra C0 olmayan Kontrolleri ve Temel Latin blok karakterlerini değiştirmek veya kaldırmak için başka bir geçiş gerekebilir.) Ancak bu iyi bir şey yapacaktır.
Tom Blodget

2

BU VB SÜRÜMÜ (YUNANCA ile çalışır):

İthalat Sistemi. Metin

İthalat Sistemi. Küreselleşme

Public Function RemoveDiacritics(ByVal s As String)
    Dim normalizedString As String
    Dim stringBuilder As New StringBuilder
    normalizedString = s.Normalize(NormalizationForm.FormD)
    Dim i As Integer
    Dim c As Char
    For i = 0 To normalizedString.Length - 1
        c = normalizedString(i)
        If CharUnicodeInfo.GetUnicodeCategory(c) <> UnicodeCategory.NonSpacingMark Then
            stringBuilder.Append(c)
        End If
    Next
    Return stringBuilder.ToString()
End Function

1
Eski bir cevap olabilir, ancak neden değişken bildirimi ve ilk atama için ayrı satırlar kullanıyorsunuz?
NiKiZe

2

HelperSharp paketini deneyin .

RemoveAccents yöntemi vardır:

 public static string RemoveAccents(this string source)
 {
     //8 bit characters 
     byte[] b = Encoding.GetEncoding(1251).GetBytes(source);

     // 7 bit characters
     string t = Encoding.ASCII.GetString(b);
     Regex re = new Regex("[^a-zA-Z0-9]=-_/");
     string c = re.Replace(t, " ");
     return c;
 }

2

Tüm .NET programımdaki aksan olmayan karakterleri aksan olmayan karakterlerle nasıl değiştiririm

C #:

//Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter 'é' is substituted by an 'e'
public string RemoveDiacritics(string s)
{
    string normalizedString = null;
    StringBuilder stringBuilder = new StringBuilder();
    normalizedString = s.Normalize(NormalizationForm.FormD);
    int i = 0;
    char c = '\0';

    for (i = 0; i <= normalizedString.Length - 1; i++)
    {
        c = normalizedString[i];
        if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().ToLower();
}

VB .NET:

'Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter "é" is substituted by an "e"'
Public Function RemoveDiacritics(ByVal s As String) As String
    Dim normalizedString As String
    Dim stringBuilder As New StringBuilder
    normalizedString = s.Normalize(NormalizationForm.FormD)
    Dim i As Integer
    Dim c As Char

    For i = 0 To normalizedString.Length - 1
        c = normalizedString(i)
        If CharUnicodeInfo.GetUnicodeCategory(c) <> UnicodeCategory.NonSpacingMark Then
            stringBuilder.Append(c)
        End If
    Next
    Return stringBuilder.ToString().ToLower()
End Function



1
Imports System.Text
Imports System.Globalization

 Public Function DECODE(ByVal x As String) As String
        Dim sb As New StringBuilder
        For Each c As Char In x.Normalize(NormalizationForm.FormD).Where(Function(a) CharUnicodeInfo.GetUnicodeCategory(a) <> UnicodeCategory.NonSpacingMark)  
            sb.Append(c)
        Next
        Return sb.ToString()
    End Function

NFC yerine NFD kullanmak, istenenlerin çok ötesinde değişikliklere neden olur.
Jon Hanna

1

Bu kişi ne dedi:

Encoding.ASCII.GetString(Encoding.GetEncoding(1251).GetBytes(text));

Aslında gibileri böler å(karakter kodu bir karakter olan 00E5, değil 0061 artı değiştirici 030Aiçine aynı olmazdı) aartı değiştirici çeşit ve ardından ASCII dönüşüm sadece bırakarak değiştirici kaldırır a.


1

Azrafe7 tarafından sağlanan özlü ve fonksiyonel kodu gerçekten seviyorum . Yani, bir uzatma yöntemine dönüştürmek için biraz değiştirdim:

public static class StringExtensions
{
    public static string RemoveDiacritics(this string text)
    {
        const string SINGLEBYTE_LATIN_ASCII_ENCODING = "ISO-8859-8";

        if (string.IsNullOrEmpty(text))
        {
            return string.Empty;
        }

        return Encoding.ASCII.GetString(
            Encoding.GetEncoding(SINGLEBYTE_LATIN_ASCII_ENCODING).GetBytes(text));
    }
}

Tüm lehçe aksanlarla çalışan tek yöntem budur. Kabul edilen cevap Ł ve ł karakterleriyle çalışmaz.
yarecky

-3

Yeteri kadar üne sahip değilim, görünüşe göre Alexander'ın mükemmel bağlantısı hakkında yorum yapamam. - Lucene makul jenerik durumlarda çalışan tek çözüm gibi görünüyor.

Basit bir kopyala yapıştır çözümü isteyenler için, işte burada, Lucene'de kod kullanmak:

string testbed = "ÁÂÄÅÇÉÍÎÓÖØÚÜÞàáâãäåæçèéêëìíîïðñóôöøúüāăčĐęğıŁłńŌōřŞşšźžșțệủ";

Console.WriteLine (Lucene.latinizeLucene (test yatağı));

AAAACEIIOOOUUTHaaaaaaaeceeeeiiiidnoooouuaacDegiLlnOorSsszzsteu

//////////

public static class Lucene
{
    // source: https://raw.githubusercontent.com/apache/lucenenet/master/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/ASCIIFoldingFilter.cs
    // idea: /programming/249087/how-do-i-remove-diacritics-accents-from-a-string-in-net (scroll down, search for lucene by Alexander)
    public static string latinizeLucene(string arg)
    {
        char[] argChar = arg.ToCharArray();

        // latinizeLuceneImpl can expand one char up to four chars - e.g. Þ to TH, or æ to ae, or in fact ⑽ to (10)
        char[] resultChar = new String(' ', arg.Length * 4).ToCharArray();

        int outputPos = Lucene.latinizeLuceneImpl(argChar, 0, ref resultChar, 0, arg.Length);

        string ret = new string(resultChar);
        ret = ret.Substring(0, outputPos);

        return ret;
    }

    /// <summary>
    /// Converts characters above ASCII to their ASCII equivalents.  For example,
    /// accents are removed from accented characters. 
    /// <para/>
    /// @lucene.internal
    /// </summary>
    /// <param name="input">     The characters to fold </param>
    /// <param name="inputPos">  Index of the first character to fold </param>
    /// <param name="output">    The result of the folding. Should be of size >= <c>length * 4</c>. </param>
    /// <param name="outputPos"> Index of output where to put the result of the folding </param>
    /// <param name="length">    The number of characters to fold </param>
    /// <returns> length of output </returns>
    private static int latinizeLuceneImpl(char[] input, int inputPos, ref char[] output, int outputPos, int length)
    {
        int end = inputPos + length;
        for (int pos = inputPos; pos < end; ++pos)
        {
            char c = input[pos];

            // Quick test: if it's not in range then just keep current character
            if (c < '\u0080')
            {
                output[outputPos++] = c;
            }
            else
            {
                switch (c)
                {
                    case '\u00C0': // À  [LATIN CAPITAL LETTER A WITH GRAVE]
                    case '\u00C1': // Á  [LATIN CAPITAL LETTER A WITH ACUTE]
                    case '\u00C2': // Â  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX]
                    case '\u00C3': // Ã  [LATIN CAPITAL LETTER A WITH TILDE]
                    case '\u00C4': // Ä  [LATIN CAPITAL LETTER A WITH DIAERESIS]
                    case '\u00C5': // Å  [LATIN CAPITAL LETTER A WITH RING ABOVE]
                    case '\u0100': // Ā  [LATIN CAPITAL LETTER A WITH MACRON]
                    case '\u0102': // Ă  [LATIN CAPITAL LETTER A WITH BREVE]
                    case '\u0104': // Ą  [LATIN CAPITAL LETTER A WITH OGONEK]
                    case '\u018F': // Ə  http://en.wikipedia.org/wiki/Schwa  [LATIN CAPITAL LETTER SCHWA]
                    case '\u01CD': // Ǎ  [LATIN CAPITAL LETTER A WITH CARON]
                    case '\u01DE': // Ǟ  [LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON]
                    case '\u01E0': // Ǡ  [LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON]
                    case '\u01FA': // Ǻ  [LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE]
                    case '\u0200': // Ȁ  [LATIN CAPITAL LETTER A WITH DOUBLE GRAVE]
                    case '\u0202': // Ȃ  [LATIN CAPITAL LETTER A WITH INVERTED BREVE]
                    case '\u0226': // Ȧ  [LATIN CAPITAL LETTER A WITH DOT ABOVE]
                    case '\u023A': // Ⱥ  [LATIN CAPITAL LETTER A WITH STROKE]
                    case '\u1D00': // ᴀ  [LATIN LETTER SMALL CAPITAL A]
                    case '\u1E00': // Ḁ  [LATIN CAPITAL LETTER A WITH RING BELOW]
                    case '\u1EA0': // Ạ  [LATIN CAPITAL LETTER A WITH DOT BELOW]
                    case '\u1EA2': // Ả  [LATIN CAPITAL LETTER A WITH HOOK ABOVE]
                    case '\u1EA4': // Ấ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE]
                    case '\u1EA6': // Ầ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE]
                    case '\u1EA8': // Ẩ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE]
                    case '\u1EAA': // Ẫ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE]
                    case '\u1EAC': // Ậ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW]
                    case '\u1EAE': // Ắ  [LATIN CAPITAL LETTER A WITH BREVE AND ACUTE]
                    case '\u1EB0': // Ằ  [LATIN CAPITAL LETTER A WITH BREVE AND GRAVE]
                    case '\u1EB2': // Ẳ  [LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE]
                    case '\u1EB4': // Ẵ  [LATIN CAPITAL LETTER A WITH BREVE AND TILDE]
                    case '\u1EB6': // Ặ  [LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW]
                    case '\u24B6': // Ⓐ  [CIRCLED LATIN CAPITAL LETTER A]
                    case '\uFF21': // A  [FULLWIDTH LATIN CAPITAL LETTER A]
                        output[outputPos++] = 'A';
                        break;
                    case '\u00E0': // à  [LATIN SMALL LETTER A WITH GRAVE]
                    case '\u00E1': // á  [LATIN SMALL LETTER A WITH ACUTE]
                    case '\u00E2': // â  [LATIN SMALL LETTER A WITH CIRCUMFLEX]
                    case '\u00E3': // ã  [LATIN SMALL LETTER A WITH TILDE]
                    case '\u00E4': // ä  [LATIN SMALL LETTER A WITH DIAERESIS]
                    case '\u00E5': // å  [LATIN SMALL LETTER A WITH RING ABOVE]
                    case '\u0101': // ā  [LATIN SMALL LETTER A WITH MACRON]
                    case '\u0103': // ă  [LATIN SMALL LETTER A WITH BREVE]
                    case '\u0105': // ą  [LATIN SMALL LETTER A WITH OGONEK]
                    case '\u01CE': // ǎ  [LATIN SMALL LETTER A WITH CARON]
                    case '\u01DF': // ǟ  [LATIN SMALL LETTER A WITH DIAERESIS AND MACRON]
                    case '\u01E1': // ǡ  [LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON]
                    case '\u01FB': // ǻ  [LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE]
                    case '\u0201': // ȁ  [LATIN SMALL LETTER A WITH DOUBLE GRAVE]
                    case '\u0203': // ȃ  [LATIN SMALL LETTER A WITH INVERTED BREVE]
                    case '\u0227': // ȧ  [LATIN SMALL LETTER A WITH DOT ABOVE]
                    case '\u0250': // ɐ  [LATIN SMALL LETTER TURNED A]
                    case '\u0259': // ə  [LATIN SMALL LETTER SCHWA]
                    case '\u025A': // ɚ  [LATIN SMALL LETTER SCHWA WITH HOOK]
                    case '\u1D8F': // ᶏ  [LATIN SMALL LETTER A WITH RETROFLEX HOOK]
                    case '\u1D95': // ᶕ  [LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK]
                    case '\u1E01': // ạ  [LATIN SMALL LETTER A WITH RING BELOW]
                    case '\u1E9A': // ả  [LATIN SMALL LETTER A WITH RIGHT HALF RING]
                    case '\u1EA1': // ạ  [LATIN SMALL LETTER A WITH DOT BELOW]
                    case '\u1EA3': // ả  [LATIN SMALL LETTER A WITH HOOK ABOVE]
                    case '\u1EA5': // ấ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE]
                    case '\u1EA7': // ầ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE]
                    case '\u1EA9': // ẩ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE]
                    case '\u1EAB': // ẫ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE]
                    case '\u1EAD': // ậ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW]
                    case '\u1EAF': // ắ  [LATIN SMALL LETTER A WITH BREVE AND ACUTE]
                    case '\u1EB1': // ằ  [LATIN SMALL LETTER A WITH BREVE AND GRAVE]
                    case '\u1EB3': // ẳ  [LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE]
                    case '\u1EB5': // ẵ  [LATIN SMALL LETTER A WITH BREVE AND TILDE]
                    case '\u1EB7': // ặ  [LATIN SMALL LETTER A WITH BREVE AND DOT BELOW]
                    case '\u2090': // ₐ  [LATIN SUBSCRIPT SMALL LETTER A]
                    case '\u2094': // ₔ  [LATIN SUBSCRIPT SMALL LETTER SCHWA]
                    case '\u24D0': // ⓐ  [CIRCLED LATIN SMALL LETTER A]
                    case '\u2C65': // ⱥ  [LATIN SMALL LETTER A WITH STROKE]
                    case '\u2C6F': // Ɐ  [LATIN CAPITAL LETTER TURNED A]
                    case '\uFF41': // a  [FULLWIDTH LATIN SMALL LETTER A]
                        output[outputPos++] = 'a';
                        break;
                    case '\uA732': // Ꜳ  [LATIN CAPITAL LETTER AA]
                        output[outputPos++] = 'A';
                        output[outputPos++] = 'A';
                        break;
                    case '\u00C6': // Æ  [LATIN CAPITAL LETTER AE]
                    case '\u01E2': // Ǣ  [LATIN CAPITAL LETTER AE WITH MACRON]
                    case '\u01FC': // Ǽ  [LATIN CAPITAL LETTER AE WITH ACUTE]
                    case '\u1D01': // ᴁ  [LATIN LETTER SMALL CAPITAL AE]
                        output[outputPos++] = 'A';
                        output[outputPos++] = 'E';
                        break;
                    case '\uA734': // Ꜵ  [LATIN CAPITAL LETTER AO]
                        output[outputPos++] = 'A';
                        output[outputPos++] = 'O';
                        break;
                    case '\uA736': // Ꜷ  [LATIN CAPITAL LETTER AU]
                        output[outputPos++] = 'A';
                        output[outputPos++] = 'U';
                        break;

        // etc. etc. etc.
        // see link above for complete source code
        // 
        // unfortunately, postings are limited, as in
        // "Body is limited to 30000 characters; you entered 136098."

                    [...]

                    case '\u2053': // ⁓  [SWUNG DASH]
                    case '\uFF5E': // ~  [FULLWIDTH TILDE]
                        output[outputPos++] = '~';
                        break;
                    default:
                        output[outputPos++] = c;
                        break;
                }
            }
        }
        return outputPos;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.