Проверьте, содержит ли строка один из 10 символов

Я использую С#, и я хочу проверить, содержит ли строка один из десяти символов, *, &, # и т.д.

Каков наилучший способ?

Ответ 1

Следующим был бы самый простой метод, на мой взгляд:

var match = str.IndexOfAny(new char[] { '*', '&', '#' }) != -1

Или, возможно, в удобной для чтения форме:

var match = str.IndexOfAny("*&#".ToCharArray()) != -1

В зависимости от требуемого контекста и производительности вы можете или не захотите кэшировать массив char.

Ответ 2

Как говорили другие, используйте IndexOfAny. Однако я бы использовал его таким образом:

private static readonly char[] Punctuation = "*&#...".ToCharArray();

public static bool ContainsPunctuation(string text)
{
    return text.IndexOfAny(Punctuation) >= 0;
}

Таким образом, вы не создадите новый массив для каждого вызова. Строку также легче сканировать, чем серию символьных литералов, IMO.

Конечно, если вы собираетесь использовать это только один раз, то потерянное создание не является проблемой, вы можете использовать:

private const string Punctuation = "*&#...";

public static bool ContainsPunctuation(string text)
{
    return text.IndexOfAny(Punctuation.ToCharArray()) >= 0;
}

или

public static bool ContainsPunctuation(string text)
{
    return text.IndexOfAny("*&#...".ToCharArray()) >= 0;
}

На самом деле это зависит от того, что вы найдете более читаемым, хотите ли вы использовать знаки пунктуации в другом месте и как часто этот метод будет вызываться.


EDIT: Здесь альтернатива методу Рида Копси для выяснения, содержит ли строка только один из символов.

private static readonly HashSet<char> Punctuation = new HashSet<char>("*&#...");

public static bool ContainsOnePunctuationMark(string text)
{
    bool seenOne = false;

    foreach (char c in text)
    {
        // TODO: Experiment to see whether HashSet is really faster than
        // Array.Contains. If all the punctuation is ASCII, there are other
        // alternatives...
        if (Punctuation.Contains(c))
        {
            if (seenOne)
            {
                return false; // This is the second punctuation character
            }
            seenOne = true;
        }
    }
    return seenOne;
}

Ответ 3

Если вы просто хотите увидеть, содержит ли он какой-либо символ, я бы рекомендовал использовать string.IndexOfAny, как это было предложено в другом месте.

Если вы хотите проверить, что строка содержит ровно один из десяти символов и только один, то это становится немного сложнее. Я считаю, что самым быстрым способом будет проверка на пересечение, а затем проверка дубликатов.

private static char[] characters = new char [] { '*','&',... };

public static bool ContainsOneCharacter(string text)
{
    var intersection = text.Intersect(characters).ToList();
    if( intersection.Count != 1)
        return false; // Make sure there is only one character in the text

    // Get a count of all of the one found character
    if (1 == text.Count(t => t == intersection[0]) )
        return true;

    return false;
}

Ответ 5

var specialChars = new[] {'\\', '/', ':', '*', '<', '>', '|', '#', '{', '}', '%', '~', '&'};

foreach (var specialChar in specialChars.Where(str.Contains))
{
    Console.Write(string.Format("string must not contain {0}", specialChar));
}

Ответ 6

Спасибо всем! (И в основном Джон!): Это позволило мне написать следующее:

    private static readonly char[] Punctuation = "$€£".ToCharArray();

    public static bool IsPrice(this string text)
    {
        return text.IndexOfAny(Punctuation) >= 0;
    }

поскольку я искал хороший способ определить, действительно ли определенная строка была ценой или предложением, например "Слишком мало для отображения".