Periksa apakah daftar berisi elemen yang berisi string dan dapatkan elemen itu


146

Saat mencari jawaban untuk pertanyaan ini, saya telah menemukan yang serupa menggunakan LINQ tapi saya belum bisa sepenuhnya memahaminya (dan dengan demikian, mengimplementasikannya), karena saya tidak terbiasa dengannya. Yang saya ingin, pada dasarnya, adalah ini:

  1. Periksa apakah ada elemen daftar yang berisi string tertentu.
  2. Jika ya, dapatkan elemen itu.

Sejujurnya aku tidak tahu bagaimana aku akan melakukan itu. Yang bisa saya pikirkan adalah ini (tidak berfungsi, tentu saja):

if (myList.Contains(myString))
    string element = myList.ElementAt(myList.IndexOf(myString));

Saya tahu MENGAPA tidak berfungsi:

  • myList.Contains()tidak kembali true, karena akan memeriksa apakah seluruh elemen daftar cocok dengan string yang saya tentukan.
  • myList.IndexOf() tidak akan menemukan kejadian, karena, seperti halnya lagi, itu akan memeriksa elemen yang cocok dengan string.

Namun, saya tidak tahu bagaimana menyelesaikan masalah ini, tetapi saya pikir saya harus menggunakan LINQ seperti yang disarankan dalam pertanyaan serupa dengan saya. Yang sedang berkata, jika itu yang terjadi di sini, saya ingin penjawab untuk menjelaskan kepada saya penggunaan LINQ dalam contoh mereka (seperti yang saya katakan, saya belum pernah repot-repot dengan waktu saya dengan C #). Terima kasih sebelumnya kawan (dan cewek?).

EDIT: Saya telah menemukan solusi; cukup loop melalui daftar, periksa apakah elemen saat ini berisi string dan kemudian setel string yang sama dengan elemen saat ini. Saya bertanya-tanya, apakah ada cara yang lebih efisien dari ini?

string myString = "bla";
string element = "";

for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Contains(myString))
        element = myList[i];
}

seperti yang saya sebutkan dalam jawaban saya, putaran mode lama (seperti yang Anda miliki sebagai pertanyaan Anda) hampir selalu tercepat. Tapi Anda bisa mengujinya jika Anda cukup peduli.
McKay

Mungkin ada beberapa string dalam daftar Anda yang berisi string Anda myString, dalam loop Anda saat ini, Anda akan mendapatkan elemen terakhir. Itu tergantung pada Anda jika Anda ingin menemukan yang pertama atau terakhir, jika Anda hanya ingin menemukan yang pertama, maka pecahkan loop setelah menemukan item.
Habib

Jawaban:


193

Anda harus dapat menggunakan Linq di sini:

var matchingvalues = myList
    .Where(stringToCheck => stringToCheck.Contains(myString));

Jika Anda hanya ingin mengembalikan item yang cocok pertama:

var match = myList
    .FirstOrDefault(stringToCheck => stringToCheck.Contains(myString));

if(match != null)
    //Do stuff

+1 - Atau ganti Wheredengan FirstOrDefaultdalam kasus kedua AndamyList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))
Habib

Jawaban yang bagus Hanya karena penasaran, mengapa: yang matchingditentukan kompiler ( var)? Karena saya tahu daftar saya adalah tipe String, apakah aman untuk digunakan string matchingdalam kasus ini?
Dimitris Iliadis

1
@JimIliadis "var" dan "string" memiliki arti yang persis sama dalam kasus ini - kompiler cukup pintar untuk mengetahui bahwa hasilnya hanya bisa berupa 'string'. var benar-benar hanya gaya penulisan kode (bila tidak menggunakan jenis anonim)
Dave Bish

mengomentari utas yang terlalu lama, tetapi menemukan satu pengecualian untuk ini. ketika Anda menggunakan firstordefault () pastikan itu dapat mengembalikan nilai default juga. jadi, anggaplah Anda melewati string kosong yaitu mystring = "" dan Anda tidak mengharapkan apa pun untuk ditampilkan, tetapi tetap saja akan menampilkan item pertama dari daftar karena Anda telah memilih firstordefault.
Pengembang Kotor

@DirtyDeveloper Tidak yakin apa yang Anda maksud dengan ini - contoh Anda akan mengembalikan 'nol, jika tidak ada string kosong dalam daftar target. Anda benar jika Anda mencoba menggunakan FirstOrDefault () pada tipe struct, mis. Daftar <int> - FirstOrDefault () akan mengembalikan '0' dan bukan nol - namun, pertanyaannya adalah tentang string
Dave Bish

29

Jawaban dasarnya adalah: Anda harus mengulang melalui loop dan memeriksa elemen apa pun yang berisi string yang ditentukan. Jadi, misalkan kodenya adalah:

foreach(string item in myList)
{
    if(item.Contains(myString))
       return item;
}

Kode yang setara, tetapi singkat, adalah:

mylist.Where(x => x.Contains(myString)).FirstOrDefault();

Di sini, x adalah parameter yang bertindak seperti "item" dalam kode di atas.


12
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
  //found
}

9
for (int i = 0; i < myList.Length; i++)
{
    if (myList[i].Contains(myString)) // (you use the word "contains". either equals or indexof might be appropriate)
    {
        return i;
    }
}

Putaran mode lama hampir selalu yang tercepat.


Karena saya mencari efisiensi, apakah Anda menyarankan bahwa metode ini lebih cepat (dengan demikian, lebih efisien)?
Dimitris Iliadis

2
Saya belum pernah mengujinya, tapi saya rasa ini akan lebih cepat. Hanya memerlukan satu kali melewati daftar, sampai ia menemukan sesuatu dan pecah lebih awal (seperti opsi Linq mungkin dilakukan jika ditulis dengan baik), tidak memiliki metode biaya overhead pemanggilan linq, atau overhead lambda dari linq juga. Bukan berarti itu adalah penyebab besar kekhawatiran, tetapi dapat menyebabkan beberapa kinerja memukul.
McKay

Mengapa tidak menggunakan List.Equals ()?
F8ER

@ V.7 Karena dia hanya ingin tahu apakah satu item dalam daftar berisi substring. list.equals bukan alat yang tepat untuk pekerjaan ["abc", "def", "ghi"] memang mengandung "hai" seperti yang dijelaskan OP. list.equals bahkan tidak mengambil tipe data yang benar.
McKay

6

Jika Anda ingin daftar string yang berisi string Anda:

var newList = myList.Where(x => x.Contains(myString)).ToList();

Pilihan lain adalah menggunakan Linq FirstOrDefault

var element = myList.Where(x => x.Contains(myString)).FirstOrDefault();

Ingatlah bahwa Containsmetode ini peka terhadap huruf besar-kecil.


1
Pengingat yang baik tentang case sensitive, mengimplementasikan StringComparison.InvariantCultureIgnoreCase
JoshYates1980

2

Anda bisa menggunakan FirstOrDefaultmetode ekstensi Linq :

string element = myList.FirstOrDefault(s => s.Contains(myString));

Ini akan mengembalikan elemen tinju yang berisi substring myString, atau nulljika tidak ada elemen seperti itu ditemukan.

Jika yang Anda butuhkan hanyalah indeks, gunakan metode List<T>kelas FindIndex:

int index = myList.FindIndex(s => s.Contains(myString));

Ini akan mengembalikan indeks elemen tinju yang berisi substring myString, atau -1jika tidak ada elemen seperti itu ditemukan.


2

Banyak jawaban bagus di sini, tetapi saya menggunakan yang sederhana menggunakan Exists , seperti di bawah ini:

foreach (var setting in FullList)
{
    if(cleanList.Exists(x => x.ProcedureName == setting.ProcedureName)) 
       setting.IsActive = true; // do you business logic here 
    else
       setting.IsActive = false;
    updateList.Add(setting);
}

2

Anda harus dapat menggunakan sesuatu seperti ini, itu berfungsi baik untuk saya:

var valuesToMatch = yourList.Where(stringCheck => stringCheck.Contains(myString));

atau sesuatu seperti ini, jika Anda perlu mencari di tempat yang tidak cocok.

 var valuesToMatch = yourList.Where(stringCheck => !stringCheck.Contains(myString));

1

kamu bisa memakai

var match=myList.Where(item=>item.Contains("Required String"));
foreach(var i in match)
{
//do something with the matched items
}

LINQ memberi Anda kemampuan untuk "meminta" koleksi data apa pun. Anda dapat menggunakan sintaksis seperti kueri basis data (pilih, di mana, dll) pada koleksi (di sini koleksi (daftar) string).

jadi Anda melakukan seperti "ambilkan saya item dari daftar Di mana memenuhi kondisi yang diberikan"

di dalam Di mana Anda menggunakan "ekspresi lambda"

untuk mengatakan secara singkat ekspresi lambda adalah sesuatu seperti (input parameter => nilai pengembalian)

jadi untuk parameter "item", ia mengembalikan "item.Berisi (" string yang diperlukan ")". Jadi itu mengembalikan true jika item berisi string dan dengan demikian akan dipilih dari daftar karena memenuhi syarat.


1

Untuk membuatnya tetap sederhana, gunakan ini;

foreach(string item in myList)//Iterate through each item.
{
 if(item.Contains("Search Term")//True if the item contains search pattern.
 {
   return item;//Return the matched item.
 }
}

Atau, untuk melakukan ini dengan for loop, gunakan ini;

    for (int iterator = 0; iterator < myList.Count; iterator++)
    {
        if (myList[iterator].Contains("String Pattern"))
        {
            return myList[iterator];
        }
    }

Hanya untuk menunjukkan, Anda melewatkan braket akhir dari salah satu baris kode .. if (item.Contains ("Istilah Pencarian"))
Alex

0

Saya belum melihat opsi bool di jawaban lain jadi saya harap kode di bawah ini akan membantu seseorang.

Gunakan saja Any()

string myString = "test";
bool exists = myList
             .Where(w => w.COLUMN_TO_CHECK.Contains(myString)).Any();

0

Dimungkinkan untuk menggabungkan Apa Saja, Dimana, Pertama dan Pertama atau Kesalahan; atau hanya menempatkan predikat di salah satu metode tersebut tergantung pada apa yang dibutuhkan.

Anda mungkin harus menghindari penggunaan First kecuali Anda ingin memiliki pengecualian yang dilemparkan ketika tidak ada kecocokan yang ditemukan. FirstOrDefault biasanya merupakan opsi yang lebih baik selama Anda tahu itu akan mengembalikan default tipe jika tidak ditemukan kecocokan (default string adalah nol, int adalah 0, bool salah, dll).

using System.Collections.Generic;
using System.Linq;


bool exists;
string firstMatch;
IEnumerable<string> matchingList;

var myList = new List<string>() { "foo", "bar", "foobar" };

exists = myList.Any(x => x.Contains("o"));
// exists => true

firstMatch = myList.FirstOrDefault(x => x.Contains("o"));
firstMatch = myList.First(x => x.Contains("o"));
// firstMatch => "foo"

firstMatch = myList.First(x => x.Contains("dark side"));
// throws exception because no element contains "dark side"

firstMatch = myList.FirstOrDefault(x => x.Contains("dark side"));
// firstMatch => null

matchingList = myList.Where(x => x.Contains("o")); 
// matchingList => { "foo", "foobar" }

Uji kode ini @ https://rextester.com/TXDL57489

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.