Bir değerin bir dizide (C #) olup olmadığını kontrol edin


109

Bir değerin C # 'da bir dizide olup olmadığını nasıl kontrol ederim?

Mesela, yazıcı isimleri listesiyle bir dizi oluşturmak istiyorum.

Bunlar, sırayla her dizeye bakacak bir yönteme beslenecek ve dizge bir dizideki bir değerle aynıysa, bu işlemi yapın.

Örneğin:

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

Bunlar yazıcıların isimleridir, PrinterSetup yöntemine beslenirler.

PrinterSetup şöyle görünecektir (bazı sözde kodlar):

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

if (printer == "jupiter")C # 'ın tanıyabileceği bir şekilde nasıl biçimlendirebilirim ?


4
Parametre adınıza bir tür (dize) vermeyi deneyin, sorun olmayacaktır.
Jon Skeet

2
Soru olarak kafam karıştı. Bir değerin dizide olup olmadığını nasıl kontrol edeceğinizi veya C # 'da dize karşılaştırması nasıl yapacağınızı mı soruyorsunuz? İkincisi ise, kullanırsınız printer.Equals("jupiter"). Eski ise, kullanın linqveprinter.Contains("jupiter")
newfurniturey

@newfurniturey Oldukça ... soru kafası karışmış, örnek kod başlık ile uyuşmuyor ve bu nedenle cevaplar da aynı şekilde karıştırılıyor; neden böyle bir oylama beni aşıyor. Ve buna gerek yok printer.Equals("jupiter")... OP'nin kodu if (printer == "jupiter")gayet iyi çalışıyor ... printerSkeet'in belirttiği gibi bir dizge olarak bildirildiği sürece .
Jim Balter

Yanıtlar:


232

Gerekli ad alanını ekleyin

using System.Linq;

Daha sonra linq Contains()yöntemini kullanabilirsiniz

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}

2
@ 0A0D. Bu cevap bence en basit / en kısa ve aynı şeyi ( How do I check if a value is in an array in C#?) ve aynı zamanda verimli elde etmenin en iyi bilinen yolu olarak en iyisidir . Döngü yok, ekstra yöntem yok. Sadece bir isim alanı fazladır ve bu büyük bir şey değildir.
Sami

6
@Sami: Linq döngüleri dahili olarak kullanır.

2
@ 0A0D Sam muhtemelen derlenmiş talimatlara değil, yazılı koda atıfta bulunuyor. Linq döngüleri ve yöntemleri dahili olarak kullanır, ancak kodlayıcıların bakış açısına göre gizli olan ve endişelenmenize gerek olmayan her şey.
2012,

1
Sağ @ 0A0D. Kodlayıcı / geliştiricinin doğru döngüye ihtiyacı olmadığını kastettim. Diziden elbette kontrolün bir döngüye ihtiyacı var :)
Sami

3
Bu kesinlikle kolay ve tavsiye edilebilir. Linq'e erişiminiz yoksa veya Linq'i kullanmak istemiyorsanız , dizinin bazı açık arabirim uygulamalarına güvenebilirsiniz . .NET 1.1'den beri ((IList)printer).Contains("Jupiter"), jenerik olmayan (kutu değer türleri vb.) Ve çok boyutlu diziler için bile çalışan elimizde . Ve .NET 2.0'dan beri daha sihirli olana sahibiz ve ((IList<string>)printer).Contains("Jupiter")bu da daha güvenli. Linq yaklaşımı .NET 3.5'te yeniydi.
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) Doğru 2) Yanlış 3) Doğru 4) Yanlış


6
Kabul edilen cevap bu olmalıdır. Bir dizi kullanırsanız, bu tamamen olası değildir, performansın önemi yoktur. Bu durumda, Linq genellikle yanlış seçimdir.
Philm

22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  

Bu genel bir örnektir - soruyla daha iyi eşleşen bir örnek verebilir misiniz?
kaz

9
Genel bir örnek olabilir ama tam da aradığım şey buydu.
Grant Birchmeier

7

Bunun gibi bir şey mi?

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
Bunu severim. Ancak, bir istisna dışında, açok boyutlu bir dizi (örneğin gibi new string[10, 20, 15]) ise başarısız olacaktır . Ayrıca, sıfırdan indekslenmemiş tek boyutlu dizilerde de başarısız olacaktır ( Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, })C #'da nadir gibi kabul ediyorum), muhtemelen yanlış bir dönüş değeri ile. Bu eksiklikleri jeneriklerle düzeltmek kolaydır:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen

Bu gibi ama Linq olmadan ve o IndexOf tek şey olduğunu doğrulamaktadır çünkü sadece sol kullanımına.
Bitterblue

6

Not: Soru, dizi dizileriyle ilgilidir. Bahsedilen rutinler, tek dizelerin .Contains yöntemi ile karıştırılmamalıdır.

Farklı C # sürümlerine atıfta bulunan ve iki nedenden dolayı genişleyen bir yanıt eklemek istiyorum:

  • Kabul edilen cevap, tamamen deyimsel C # olan Linq'i gerektirir, ancak maliyetsiz gelmez ve C # 2.0 veya altında mevcut değildir. Bir dizi söz konusu olduğunda performans önemli olabilir, bu nedenle Array yöntemlerinde kalmak isteyeceğiniz durumlar vardır.

  • Bunu bir fonksiyona koymasının istendiği soruya hiçbir cevap doğrudan katılmaz (Bazı cevaplar aynı zamanda dizgeleri dizgi dizileriyle karıştırdığı için, bu tamamen önemsiz değildir).

Array.Exists () bir C # /. NET 2.0 yöntemidir ve Linq gerektirmez. Dizilerde arama O (n). Daha hızlı erişim için HashSet veya benzer koleksiyonları kullanın.

.NET 3.5'ten beri genel bir yöntem de vardır 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");
   }
}

Linq'i dahil etmeden tüm diziler için aynı / benzer ".Contains" i elde etmek için sözdizimsel şekeri eklemek için kendi genişletme yöntemi (C # 3.0 ve üstü) yazabilirsiniz:

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

Bu durumda ArrayContains()Linq'in İçerir yöntemi değil, bu yöntem kullanılır.

Başka bir yerde bahsedilen .Contains yöntemleri, List<T>.Contains(C # 2.0'dan ArrayList.Containsberi ) veya (C # 1.1'den beri) anlamına gelir, ancak doğrudan dizilerin kendisine atıfta bulunmaz.


1
Linq Contains () ile karışıklığı önlemek için adı ArrayContains () olarak değiştirmenizi öneririm
peter.cyc

Bunu yaptım, ancak karşı argümanlar da var: Farklı veri türleri için aynı adı kullanmak, özellikle de Linq ayarı göz önünde bulundurularak çok biçimliliğin temel fikri. Farklı isimler kullanmak polimorf değildir. Ancak okunabilirlik ve yanlış anlamalardan kaçınmanın kazanacağını düşünüyorum, yani evet.
Philm

4

Sadece yönteminizde bir şeyi kaçırıyorsunuz:

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

Sadece ekleyin stringve iyi olacaksınız.


3

Sorununuzun ne olduğu çok net değil, ancak şuna benzer bir şey istediğiniz gibi görünüyor:

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

    if( printer.Exists( p => p.Equals( "jupiter" ) ) )
    {
        ...
    }

2

Arama performansı uğruna HashSet<T>Sınıfı kullanmayı düşünün :

Bu yöntem bir O (1) işlemidir.

- HashSet<T>.ContainsYöntem (T), MSDN .

Örneğin:

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

Bir listedeki kopyaları nasıl bulacağımı ve onları nasıl kaldıracağımı güzel bir şekilde bulmak için şimdi 2 saatten fazla aradım . İşte en basit cevap:

//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();

Çıktı şu şekilde görünecektir: Yinelenen Öğeler, farklı adı verilen yeni listeden kaldırılacaktır!

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.