[C#] 不區分大小寫'包含(字符串)'


Answers

您可以使用String.IndexOf方法並傳遞StringComparison.OrdinalIgnoreCase作為要使用的搜索類型:

string title = "STRING";
bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;

更好的是為字符串定義一個新的擴展方法:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source?.IndexOf(toCheck, comp) >= 0;
    }
}

請注意,這是空傳播 ?. 自C#6.0(VS 2015)開始提供,適用於舊版本

   if(source==null) return false;
   return source.IndexOf(toCheck, comp) >= 0;

用法:

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);
Question

有沒有辦法讓以下回報成真?

string title = "ASTRINGTOTEST";
title.Contains("string");

似乎沒有超負荷允許我設置區分大小寫。目前,我大寫他們兩個,但這只是愚蠢的。

UPDATE
我提到的愚蠢是上下套管帶來的i18n問題。

UPDATE
這個問題是古老的,從那以後,我意識到我要求一個簡單的答案,如果你關心的是一個非常廣泛和困難的話題,那麼這個問題應該是完全的。
對於大多數情況下,在單語言,英語代碼基礎上, this答案就足夠了。 我懷疑是因為大多數來這裡的人都屬於這個類別,這是最受歡迎的答案。
然而, This答案帶來了固有的問題,即我們無法比較文本不區分大小寫,直到我們知道兩個文本是相同的文化,並且我們知道該文化是什麼。 這可能是一個不太流行的答案,但我認為它更正確,這就是為什麼我這樣標記它。




簡單的方法為新手:

title.ToLower().Contains("string");//of course "string" is lowercase.



VisualBasic程序集的InStr方法是最好的,如果你有關於國際化的問題(或者你可以重新實現它)。 在它看來,dotNeetPeek表明,它不僅涵蓋大小寫,而且還包括假名類型和全角與半角字符(大部分與亞洲語言相關,儘管也有全角版本的羅馬字母)。 我正在跳過一些細節,但請查看私有方法InternalInStrText

private static int InternalInStrText(int lStartPos, string sSrc, string sFind)
{
  int num = sSrc == null ? 0 : sSrc.Length;
  if (lStartPos > num || num == 0)
    return -1;
  if (sFind == null || sFind.Length == 0)
    return lStartPos;
  else
    return Utils.GetCultureInfo().CompareInfo.IndexOf(sSrc, sFind, lStartPos, CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth);
}



這很乾淨簡單。

Regex.IsMatch(file,fileNamestr,RegexOptions.IgnoreCase)



public static class StringExtension
{
    #region Public Methods

    public static bool ExContains(this string fullText, string value)
    {
        return ExIndexOf(fullText, value) > -1;
    }

    public static bool ExEquals(this string text, string textToCompare)
    {
        return text.Equals(textToCompare, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExHasAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index]) == false) return false;
        return true;
    }

    public static bool ExHasEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return true;
        return false;
    }

    public static bool ExHasNoEquals(this string text, params string[] textArgs)
    {
        return ExHasEquals(text, textArgs) == false;
    }

    public static bool ExHasNotAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return false;
        return true;
    }

    /// <summary>
    /// Reports the zero-based index of the first occurrence of the specified string
    /// in the current System.String object using StringComparison.InvariantCultureIgnoreCase.
    /// A parameter specifies the type of search to use for the specified string.
    /// </summary>
    /// <param name="fullText">
    /// The string to search inside.
    /// </param>
    /// <param name="value">
    /// The string to seek.
    /// </param>
    /// <returns>
    /// The index position of the value parameter if that string is found, or -1 if it
    /// is not. If value is System.String.Empty, the return value is 0.
    /// </returns>
    /// <exception cref="ArgumentNullException">
    /// fullText or value is null.
    /// </exception>
    public static int ExIndexOf(this string fullText, string value)
    {
        return fullText.IndexOf(value, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExNotEquals(this string text, string textToCompare)
    {
        return ExEquals(text, textToCompare) == false;
    }

    #endregion Public Methods
}



像這樣:

string s="AbcdEf";
if(s.ToLower().Contains("def"))
{
    Console.WriteLine("yes");
}



你可以使用string.indexof ()函數。 這將不區分大小寫




最終,通用的“包含”操作歸結為這樣的功能,

/// <summary>
/// Determines whether the source contains the sequence.
/// </summary>
/// <typeparam name="T">The type of the items in the sequences.</typeparam>
/// <param name="sourceEnumerator">The source enumerator.</param>
/// <param name="sequenceEnumerator">The sequence enumerator.</param>
/// <param name="equalityComparer">An equality comparer.</param>
/// <remarks>
/// An empty sequence will return <c>true</c>.
/// The sequence must support <see cref="IEnumerator.Reset"/>
/// if it does not begin the source.
/// </remarks>
/// <returns>
/// <c>true</c> if the source contains the sequence;
/// otherwise <c>false</c>.
/// </returns>
public static bool Contains<T>(
    IEnumerator<T> sourceEnumerator,
    IEnumerator<T> sequenceEnumerator,
    IEqualityComparer<T> equalityComparer)
{
    if (equalityComparer == null)
    {
        equalityComparer = EqualityComparer<T>.Default;
    }

    while (sequenceEnumerator.MoveNext())
    {
        if (sourceEnumerator.MoveNext())
        {
            if (!equalityComparer.Equals(
                sourceEnumerator.Current,
                sequenceEnumerator.Current))
            {
                sequenceEnumerator.Reset();
            }
        }
        else
        {
            return false;
        }
    }

    return true;
}

這可以簡單地包裝在接受IEnumerable的擴展版本中,像這樣,

public static bool Contains<T>(
        this IEnumerable<T> source,
        IEnumerable<T> sequence,
        IEqualityComparer<T> equalityComparer = null)
{
    if (sequence == null)
    {
        throw new ArgumentNullException("sequence");
    }

    using(var sequenceEnumerator = sequence.GetEnumerator())
    using(var sourceEnumerator = source.GetEnumerator())
    {
        return Contains(
            sourceEnumerator,
            sequenceEnumerator,
            equalityComparer);
    }
}

現在,這將適用於任何序列(包括字符串)的序數比較,因為string實現了IEnumerable<char>

// The optional parameter ensures the generic overload is invoked
// not the string.Contains() implementation.
"testable".Contains("est", EqualityComparer<char>.Default)

但是,正如我們所知,字符串不是通用的,它們是專用的。 有兩個關鍵因素在起作用。

  1. “套管”問題本身俱有各種語言相關的邊界情況。
  2. 關於一組“文本元素”(字母/數字/符號等)如何由Unicode代碼點表示以及什麼有效的字符序列可以表示給定字符串的相關問題,在these answers中擴展了細節。

淨效應是一樣的。 您可能聲明的字符串在語言上相同,可以通過字符的不同組合來有效表示。 更重要的是,不同文化之間有效性變化的規則。

所有這些都會導致一個像這樣的基於“Contains”實現的專用字符串。

using System.Globalization;

public static bool Contains(
         this string source,
         string value,
         CultureInfo culture = null,
         CompareOptions options = CompareOptions.None)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }

    var compareInfo = culture == null ? 
            CultureInfo.CurrentCulture.CompareInfo :
            culture.CompareInfo;

    var sourceEnumerator = StringInfo.GetTextElementEnumerator(source);
    var sequenceEnumerator = StringInfo.GetTextElementEnumerator(value);

    while (sequenceEnumerator.MoveNext())
    {
        if (sourceEnumerator.MoveNext())
        {
            if (!(compareInfo.Compare(
                    sourceEnumerator.Current,
                    sequenceEnumerator.Current,
                    options) == 0))
            {
                sequenceEnumerator.Reset();
            }
        }
        else
        {
            return false;
        }
    }

    return true;
}

這個函數可以用來執行不區分大小寫的文化特定的“包含”,無論標準化字符串如何,它都可以工作。 例如

"testable".Contains("EST", StringComparer.CurrentCultureIgnoreCase)



這與其他示例非常相似,但我決定將enum簡化為bool,因為通常不需要其他替代方法。 這是我的例子:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, bool bCaseInsensitive )
    {
        return source.IndexOf(toCheck, bCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) >= 0;
    }
}

用法如下所示:

if( "main String substring".Contains("SUBSTRING", true) )
....



答案的一個問題是,如果字符串為空,它將引發異常。 您可以添加,作為一個支票,所以它不會:

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    if (string.IsNullOrEmpty(toCheck) || string.IsNullOrEmpty(source))
        return true;

    return source.IndexOf(toCheck, comp) >= 0;
} 



使用Regex的替代解決方案:

bool contains = Regex.IsMatch("StRiNG to search", "string", RegexOptions.IgnoreCase);

注意

正如@cHao在他的評論中指出的那樣,有一些情況會導致此解決方案返回不正確的結果。 在你實施這個解決方案之前,確保你知道你在做什麼。






Links