Kiểm tra xem danh sách có chứa phần tử chứa chuỗi không và lấy phần tử đó


146

Trong khi tìm kiếm câu trả lời cho câu hỏi này, tôi đã gặp phải những câu hỏi tương tự sử dụng LINQ nhưng tôi chưa thể hiểu hết về chúng (và do đó, thực hiện chúng), vì tôi không quen với nó. Những gì tôi muốn, về cơ bản, là đây:

  1. Kiểm tra xem có phần tử nào trong danh sách chứa một chuỗi cụ thể không.
  2. Nếu có, hãy lấy phần tử đó.

Tôi thực sự không biết làm thế nào tôi sẽ làm điều đó. Những gì tôi có thể đưa ra là điều này (tất nhiên không hoạt động):

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

Tôi biết TẠI SAO nó không hoạt động:

  • myList.Contains()không trả về true, vì nó sẽ kiểm tra xem toàn bộ thành phần của danh sách có khớp với chuỗi tôi đã chỉ định hay không.
  • myList.IndexOf() sẽ không tìm thấy sự xuất hiện, vì, vì nó là trường hợp một lần nữa, nó sẽ kiểm tra một phần tử khớp với chuỗi.

Tuy nhiên, tôi không biết làm thế nào để giải quyết vấn đề này, nhưng tôi cho rằng tôi sẽ phải sử dụng LINQ như được đề xuất trong các câu hỏi tương tự với tôi. Điều đó đang được nói, nếu đó là trường hợp ở đây, tôi muốn người trả lời giải thích cho tôi về việc sử dụng LINQ trong ví dụ của họ (như tôi đã nói, tôi đã không bận tâm đến nó trong thời gian sử dụng C #). Cảm ơn các bạn trước (và các cô gái?).

EDIT: Tôi đã đưa ra một giải pháp; chỉ cần lặp qua danh sách, kiểm tra xem phần tử hiện tại có chứa chuỗi không và sau đó đặt chuỗi bằng với phần tử hiện tại. Tôi đang tự hỏi, mặc dù, có cách nào hiệu quả hơn thế này?

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

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

như tôi đã đề cập trong câu trả lời của mình, các vòng lặp thời trang cũ (như bạn có như câu hỏi của bạn) hầu như luôn luôn nhanh nhất. Nhưng bạn có thể kiểm tra nó một cách hoàn hảo nếu bạn quan tâm đúng mức.
McKay

Có thể có nhiều chuỗi trong danh sách của bạn chứa chuỗi của bạn myString, trong vòng lặp hiện tại của bạn, bạn sẽ nhận được phần tử cuối cùng. Nó phụ thuộc vào bạn nếu bạn muốn tìm cái đầu tiên hay cái cuối cùng, nếu bạn chỉ muốn tìm cái đầu tiên, sau đó phá vỡ vòng lặp sau khi tìm thấy vật phẩm.
Habib

Câu trả lời:


193

Bạn sẽ có thể sử dụng Linq tại đây:

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

Nếu bạn chỉ muốn trả lại mục phù hợp đầu tiên:

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

if(match != null)
    //Do stuff

+1 - Hoặc thay thế Wherebằng FirstOrDefaulttrong trường hợp thứ hai của bạnmyList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))
Habib

Câu trả lời chính xác. Tuy nhiên, chỉ vì tò mò: tại sao nó lại matchingđược xác định bởi trình biên dịch ( var)? Vì tôi biết rằng danh sách của tôi thuộc loại String, nên sử dụng string matchingtrong trường hợp này có an toàn không?
Dimitris Iliadis

1
@JimIliadis "var" và "chuỗi" có nghĩa chính xác là điều tương tự trong trường hợp này - trình biên dịch đủ thông minh để biết rằng kết quả chỉ có thể là 'chuỗi'. var thực sự chỉ là một thứ theo phong cách mã hóa (khi không sử dụng các loại ẩn danh)
Dave Bish

bình luận về chủ đề quá cũ, nhưng tìm thấy một ngoại lệ về điều này. khi bạn sử dụng Firstordefault (), hãy đảm bảo rằng nó cũng có thể trả về giá trị mặc định. vì vậy, giả sử bạn đang truyền một chuỗi empy tức là mystring = "" và bạn đang mong đợi không có gì hiển thị, nhưng nó vẫn sẽ hiển thị mục đầu tiên của danh sách vì bạn đã chọn Firstordefault.
Nhà phát triển bẩn

@DentyDeveloper Không chắc ý của bạn là gì - ví dụ của bạn sẽ trả về 'null, nếu không có chuỗi trống trong danh sách đích. Bạn đúng nếu bạn đang cố sử dụng FirstOrDefault () trên loại cấu trúc, ví dụ: Danh sách <int> - FirstOrDefault () sẽ trả về '0' và không null - tuy nhiên, câu hỏi cụ thể là về chuỗi
Dave Bish

29

Câu trả lời cơ bản là: bạn cần lặp qua vòng lặp và kiểm tra bất kỳ phần tử nào chứa chuỗi đã chỉ định. Vì vậy, giả sử mã là:

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

Mã tương đương, nhưng ngắn gọn là:

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

Ở đây, x là một tham số hoạt động như "mục" trong đoạn mã trên.


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

Vòng lặp thời trang cũ hầu như luôn luôn là nhanh nhất.


Vì tôi đi cho hiệu quả, bạn có gợi ý rằng phương pháp này nhanh hơn (do đó, hiệu quả hơn)?
Dimitris Iliadis

2
Tôi chưa hoàn thành thử nghiệm nó, nhưng tôi đoán rằng điều này sẽ nhanh hơn. Chỉ bao giờ yêu cầu một người đi qua danh sách, cho đến khi nó tìm thấy thứ gì đó và thoát ra sớm (như các tùy chọn Linq có thể làm nếu được viết tốt), cũng không có phương thức gọi phương thức của linq, hoặc chi phí lambda của linq. Không phải đó là những nguyên nhân lớn gây lo ngại, nhưng có thể gây ra một số hiệu suất.
McKay

Tại sao không sử dụng List.Equals ()?
F8ER

@ V.7 Bởi vì anh ta chỉ muốn biết nếu một mục trong danh sách có chứa một chuỗi con. list.equals không phải là công cụ chính xác cho công việc ["abc", "def", "ghi"] không chứa "hi" theo cách mà OP mô tả. list.equals thậm chí không lấy các kiểu dữ liệu chính xác.
McKay

6

Nếu bạn muốn một danh sách các chuỗi chứa chuỗi của bạn:

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

Một tùy chọn khác là sử dụng Linq FirstOrDefault

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

Hãy nhớ rằng Containsphương pháp là trường hợp nhạy cảm.


1
Nhắc nhở tốt về trường hợp nhạy cảm, triển khai StringComparison.InvariantCARMIgnoreCase
JoshYates1980

2

Bạn có thể sử dụng FirstOrDefaultphương pháp mở rộng của Linq :

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

Điều này sẽ trả về phần tử nắm tay chứa chuỗi con myStringhoặc nullnếu không tìm thấy phần tử nào như vậy.

Nếu tất cả những gì bạn cần là chỉ mục, hãy sử dụng phương thức List<T>của lớp FindIndex:

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

Điều này sẽ trả về chỉ mục của phần tử nắm tay chứa chuỗi con myStringhoặc -1nếu không tìm thấy phần tử nào như vậy.


2

Nhiều câu trả lời hay ở đây, nhưng tôi sử dụng một câu trả lời đơn giản bằng Exists , như sau:

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

Bạn sẽ có thể sử dụng một cái gì đó như thế này, nó đã hoạt động tốt với tôi:

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

hoặc một cái gì đó như thế này, nếu bạn cần nhìn vào nơi nó không phù hợp.

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

1

bạn có thể dùng

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

LINQ cung cấp cho bạn khả năng "truy vấn" bất kỳ bộ sưu tập dữ liệu nào. Bạn có thể sử dụng cú pháp như truy vấn cơ sở dữ liệu (chọn, ở đâu, v.v.) trên bộ sưu tập (ở đây là bộ sưu tập (danh sách) chuỗi).

vì vậy bạn đang làm như "lấy cho tôi các mục từ danh sách Nơi nó thỏa mãn một điều kiện nhất định"

bên trong Nơi bạn đang sử dụng "biểu thức lambda"

để nói ngắn gọn biểu thức lambda là một cái gì đó như (tham số đầu vào => giá trị trả về)

vì vậy đối với tham số "item", nó trả về "item.Contains (" chuỗi bắt buộc ")". Vì vậy, nó trả về true nếu mục chứa chuỗi và do đó nó được chọn từ danh sách vì nó thỏa mãn điều kiện.


1

Để giữ cho nó đơn giản sử dụng này;

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.
 }
}

Ngoài ra, để làm điều này với vòng lặp, sử dụng cái này;

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

Chỉ cần chỉ ra, bạn đã bỏ lỡ một dấu ngoặc kết thúc khỏi một trong các dòng mã .. if (item.Contains ("Tìm kiếm thuật ngữ"))
Alex

0

Tôi chưa thấy tùy chọn bool trong các câu trả lời khác vì vậy tôi hy vọng đoạn mã dưới đây sẽ giúp được ai đó.

Chỉ dùng Any()

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

0

Có thể kết hợp Any, Where, First và FirstOrDefault; hoặc chỉ đặt vị ngữ trong bất kỳ phương thức nào tùy thuộc vào những gì cần thiết.

Bạn có thể nên tránh sử dụng Đầu tiên trừ khi bạn muốn có một ngoại lệ được ném khi không tìm thấy kết quả khớp. FirstOrDefault thường là tùy chọn tốt hơn miễn là bạn biết nó sẽ trả về kiểu mặc định nếu không tìm thấy kết quả khớp (mặc định của chuỗi là null, int là 0, bool là false, v.v.).

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

Kiểm tra mã này @ https://rextester.com/TXDL57361

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.