Проверить, находится ли значение в массиве (C #)

109

Как проверить, находится ли значение в массиве в C #?

Например, я хочу создать массив со списком имен принтеров.

Они будут переданы в метод, который будет просматривать каждую строку по очереди, и если строка совпадает со значением в массиве, выполните это действие.

Например:

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
foreach (p in printer)
{
   PrinterSetup(p);     
}

Это имена принтеров, они передаются в метод PrinterSetup.

PrinterSetup будет выглядеть примерно так (какой-то псевдокод):

public void PrinterSetup(printer)
{
   if (printer == "jupiter") 
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

Как отформатировать if (printer == "jupiter")так, чтобы C # мог распознать?

Сесил Родригес
источник
4
Попробуйте дать вашему параметру тип (строку), и все будет хорошо.
Джон Скит
2
Я как бы запутался в вопросе. Вы спрашиваете, как проверить, находится ли значение в массиве, или как выполнить сравнение строк в C #? Если это последнее, вы должны использовать printer.Equals("jupiter"). Если это первое, используйте linqиprinter.Contains("jupiter")
новая мебель
@newfurniturey Совершенно верно ... вопрос запутанный, код примера не соответствует заголовку, и поэтому ответы также запутаны; почему за такое дерьмо голосуют, не понимаю. И в этом нет необходимости printer.Equals("jupiter")... Код OP if (printer == "jupiter")работает нормально ... до тех пор, пока printerон объявлен как строка, как отмечает Скит.
Джим Балтер

Ответы:

232

Добавьте необходимое пространство имен

using System.Linq;

Затем вы можете использовать Contains()метод linq

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}
Дмитрий
источник
2
@ 0A0D. Я считаю, что этот ответ лучше всего - это самый простой / кратчайший и хорошо известный способ добиться того же ( How do I check if a value is in an array in C#?), а также эффективно. Нет цикла, нет лишнего метода. Просто пространство имен является лишним, что не имеет большого значения.
Sami
6
@Sami: Linq внутренне использует циклы.
2
@ 0A0D Сэм, вероятно, имеет в виду написанный код, а не скомпилированные инструкции. Linq внутренне использует циклы и методы, но с точки зрения программистов все это скрыто и не о чем беспокоиться.
Trisped
1
Справа @ 0A0D. Я имел в виду, что кодеру / разработчику не нужно было править цикл. Конечно, проверка из массива требует цикла :)
Sami
3
Это, безусловно, легко и рекомендуется. Если у вас нет доступа к Linq или вы не хотите использовать Linq, вы можете положиться на некоторую явную реализацию интерфейса массива. Начиная с .NET 1.1, у нас ((IList)printer).Contains("Jupiter")есть не общий (могут быть типы значений и т. Д.), Который работает даже для многомерных массивов. А начиная с .NET 2.0 у нас есть более волшебное, ((IList<string>)printer).Contains("Jupiter")более безопасное по типу. Подход Linq был новинкой в ​​.NET 3.5.
Jeppe Stig Nielsen
29
   string[] array = { "cat", "dot", "perls" };

// Use Array.Exists in different ways.
bool a = Array.Exists(array, element => element == "perls");
bool b = Array.Exists(array, element => element == "python");
bool c = Array.Exists(array, element => element.StartsWith("d"));
bool d = Array.Exists(array, element => element.StartsWith("x"));

// Display bools.
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
----------------------------output-----------------------------------

1) верно 2) неверно 3) верно 4) неверно


источник
6
Это должен быть принятый ответ. Если вы используете массив, это не совсем маловероятно, производительность имеет значение. В этом случае Linq часто оказывается неправильным выбором.
Филм
22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  
Гость
источник
Это общий пример - можете ли вы привести тот, который лучше соответствует вашему вопросу?
kaz
9
Это может быть общий пример, но это именно то, что я искал.
Grant Birchmeier
7

Что-то вроде этого?

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
PrinterSetup(printer);

// redefine PrinterSetup this way:
public void PrinterSetup(string[] printer)
{
    foreach (p in printer.Where(c => c == "jupiter"))
    {
        Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
    }
}
code4life
источник
7
    public static bool Contains(Array a, object val)
    {
        return Array.IndexOf(a, val) != -1;
    }
Раз Мегрелидзе
источник
2
Мне это нравится. Однако это не удастся, если aэто многомерный массив (например, new string[10, 20, 15]например), за исключением. Он также потерпит неудачу с одномерными массивами, которые не проиндексированы с нуля (например Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, }), редко в C #, я признаю), с возможно неправильным возвращаемым значением. Эти недостатки легко исправить с помощью дженериков:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen
Мне нравится это, но только потому , что без Linq и это подтверждает , что IndexOf это единственное , что осталось в использовании.
Bitterblue
6

Примечание: речь идет о массивах строк. Упомянутые подпрограммы не следует смешивать с методом одиночных строк .Contains.

Я хотел бы добавить расширяющий ответ, относящийся к различным версиям C #, и по двум причинам:

  • Для принятого ответа требуется Linq, который является совершенно идиоматическим C #, хотя он не обходится без затрат и недоступен в C # 2.0 или ниже. Когда задействован массив, производительность может иметь значение, поэтому есть ситуации, когда вы хотите остаться с методами массива.

  • Нет ответа непосредственно на вопрос, в котором было предложено также поместить это в функцию (поскольку некоторые ответы также смешивают строки с массивами строк, это не совсем неважно).

Array.Exists () - это метод C # /. NET 2.0, который не требует Linq. Поиск в массивах - O (n). Для еще более быстрого доступа используйте HashSet или аналогичные коллекции.

Начиная с .NET 3.5 существует также общий метод Array<T>.Exists():

public void PrinterSetup(string[] printer)
{
   if (Array.Exists(printer, x => x == "jupiter"))
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

Вы можете написать собственный метод расширения (C # 3.0 и выше), чтобы добавить синтаксический сахар, чтобы получить такие же / похожие ".Contains", что и для строк для всех массивов, без включения Linq:

// Using the generic extension method below as requested.
public void PrinterSetup(string[] printer)
{
   if (printer.ArrayContains("jupiter"))
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

public static bool ArrayContains<T>(this T[] thisArray, T searchElement)
{
   // If you want this to find "null" values, you could change the code here
   return Array.Exists<T>(thisArray, x => x.Equals(searchElement));
}

В этом случае используется этот ArrayContains()метод, а не метод Contains в Linq.

Упомянутые в другом месте методы .Contains относятся к List<T>.Contains(начиная с C # 2.0) или ArrayList.Contains(начиная с C # 1.1), но не непосредственно к самим массивам.

Филм
источник
1
Я предлагаю изменить имя на ArrayContains (), чтобы избежать путаницы с Linq Contains ()
peter.cyc
Я сделал это, хотя есть и аргументы против: основная идея полиморфизма - использовать одно и то же имя для разных типов данных, особенно с учетом настройки Linq. Использование разных имен не является полиморфом. Но читаемость и избегание недоразумений победят, я думаю, так что да.
Филм,
4

Вам просто чего-то не хватает в вашем методе:

public void PrinterSetup(string printer)
{
   if (printer == "jupiter") 
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
   }
}

Просто добавь stringи все будет хорошо.


источник
3

Не очень понятно, в чем ваша проблема, но похоже, что вы хотите что-то вроде этого:

    List<string> printer = new List<string>( new [] { "jupiter", "neptune", "pangea", "mercury", "sonic" } );

    if( printer.Exists( p => p.Equals( "jupiter" ) ) )
    {
        ...
    }
Брэндон Моретц
источник
2

Подумайте об использовании HashSet<T>Class для повышения производительности поиска:

Этот метод является операцией O (1).

- HashSet<T>.ContainsМетод (T), MSDN .

Например:

class PrinterInstaller
{
    private static readonly HashSet<string> PrinterNames = new HashSet<string>
        {
            "jupiter", "neptune", "pangea", "mercury", "sonic"
        };

    public void Setup(string printerName)
    {
        if (!PrinterNames.Contains(printerName))
        {
            throw new ArgumentException("Unknown printer name", "printerName");
        }
        // ...
    }
}
Сергей Брунов
источник
1

Я искал сейчас более 2 часов, чтобы найти хороший способ найти дубликаты в списке и как их удалить . Вот самый простой ответ:

//Copy the string array with the filtered data of the analytics db into an list
// a list should be easier to use
List<string> list_filtered_data = new List<string>(analytics_db_filtered_data);

// Get distinct elements and convert into a list again.
List<string> distinct = list_filtered_data.Distinct().ToList();

Результат будет выглядеть следующим образом: Дублированные элементы будут удалены в новом списке, который называется отличным!

Рикардо Ферчер
источник