Перевірте, чи є значення в масиві (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

@newfurniturey Досить так ... запитання плутається, приклад коду не відповідає заголовку, і, таким чином, відповіді також плутаються; чому подібне лайно, як це, стає поза мною. І робити це не потрібно printer.Equals("jupiter")... Код ОП if (printer == "jupiter")працює чудово ... до тих пір, printerпоки оголошено рядок, як зазначає Скіт.
Джим Балтер

Відповіді:


231

Додайте необхідний простір імен

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#?) і ефективного. Немає циклу, не зайвий метод Просто зайвий простір імен - це не велика річ.
Самі

6
@Sami: Linq використовує петлі внутрішньо.

2
@ 0A0D Sam, ймовірно, посилається на письмовий код, а не на компільовані інструкції. Linq використовує петлі та методи внутрішньо, але з точки зору кодерів все, що приховано, і про це не потрібно хвилюватися.
Trisped

1
Право @ 0A0D. Я мав на увазі, що кодер / розробник не потребував правого циклу. Перевірка курсу з масиву потребує циклу :)
Самі

3
Це, звичайно, легко і рекомендується. Якщо у вас немає доступу до Linq або ви не хочете використовувати Linq, ви можете покластися на явну реалізацію інтерфейсу масиву. Оскільки .NET 1.1 у нас є ((IList)printer).Contains("Jupiter")негенеричним (може вказувати типи значень тощо) і працює навіть для багатовимірних масивів. А оскільки .NET 2.0 у нас є більш чарівний, ((IList<string>)printer).Contains("Jupiter")який є більш безпечним для типу. Підхід Linq був новим у .NET 3.5.
Джеппе Стіг Нільсен

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"))
{

}  

Це загальний приклад - чи можете ви надати той, який краще відповідає питанню?
каз

9
Це може бути загальний приклад, але саме це я шукав.
Грант Бірхмайер

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"");
    }
}

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()метод, а не метод Links, який містить 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>класу заради продуктивності пошуку:

Цей метод є операцією 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();

Вихід буде виглядати приблизно так: Дублюючі елементи будуть видалені з нового списку під назвою окремий!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.