C# 如何使用 LINQ Contains(string[]) 而不是 Contains(string)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/194930/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:33:09  来源:igfitidea点击:

How do I use LINQ Contains(string[]) instead of Contains(string)

c#linqstringcontains

提问by SpoiledTechie.com

I got one big question.

我有一个大问题。

I got a linq query to put it simply looks like this:

我得到了一个 linq 查询,它看起来像这样:

from xx in table
where xx.uid.ToString().Contains(string[])
select xx

The values of the string[]array would be numbers like (1,45,20,10,etc...)

string[]数组的值将是像 (1,45,20,10,etc...)

the Default for .Containsis .Contains(string).

默认为.ContainsIS .Contains(string)

I need it to do this instead: .Contains(string[])...

我需要它来代替: .Contains(string[])...

EDIT :One user suggested writing an extension class for string[]. I would like to learn how, but any one willing to point me in the right direction?

编辑:一位用户建议为string[]. 我想学习如何学习,但有人愿意为我指明正确的方向吗?

EDIT :The uid would also be a number. That's why it is converted to a string.

编辑:uid 也将是一个数字。这就是它被转换为字符串的原因。

Help anyone?

帮助任何人?

采纳答案by tvanfosson

spoulson has it nearly right, but you need to create a List<string>from string[]first. Actually a List<int>would be better if uid is also int. List<T>supports Contains(). Doing uid.ToString().Contains(string[])would imply that the uid as a string contains all of the values of the array as a substring??? Even if you did write the extension method the sense of it would be wrong.

spoulson 几乎是正确的,但您需要List<string>string[]一开始就创建一个。实际上,List<int>如果 uid 也是a会更好intList<T>支持Contains(). 这样做 uid.ToString().Contains(string[])意味着 uid 作为字符串包含数组的所有值作为子字符串???即使您确实编写了扩展方法,它的意义也是错误的。

[EDIT]

[编辑]

Unless you changed it around and wrote it for string[]as Mitch Wheat demonstrates, then you'd just be able to skip the conversion step.

除非您string[]像 Mitch Wheat 演示的那样更改它并编写它,否则您只能跳过转换步骤。

[ENDEDIT]

[结束]

Here is what you want, if you don't do the extension method (unless you already have the collection of potential uids as ints -- then just use List<int>()instead). This uses the chained method syntax, which I think is cleaner, and does the conversion to int to ensure that the query can be used with more providers.

这就是您想要的,如果您不使用扩展方法(除非您已经将潜在的 uid 集合作为整数——然后使用List<int>())。这使用了我认为更简洁的链式方法语法,并转换为 int 以确保查询可以用于更多提供者。

var uids = arrayofuids.Select(id => int.Parse(id)).ToList();

var selected = table.Where(t => uids.Contains(t.uid));

回答by spoulson

How about:

怎么样:

from xx in table
where stringarray.Contains(xx.uid.ToString())
select xx

回答by Mitch Wheat

This is an example of one way of writing an extension method (note: I wouldn't use this for very large arrays; another data structure would be more appropriate...):

这是编写扩展方法的一种方式的示例(注意:我不会将它用于非常大的数组;另一种数据结构会更合适...):

namespace StringExtensionMethods
{
    public static class StringExtension
    {
        public static bool Contains(this string[] stringarray, string pat)
        {
            bool result = false;

            foreach (string s in stringarray)
            {
                if (s == pat)
                {
                    result = true;
                    break;
                }
            }

            return result;
        }
    }
}

回答by ctrlShiftBryan

I believe you could also do something like this.

我相信你也可以做这样的事情。

from xx in table
where (from yy in string[] 
       select yy).Contains(xx.uid.ToString())
select xx

回答by JaredPar

Try the following.

请尝试以下操作。

string input = "someString";
string[] toSearchFor = GetSearchStrings();
var containsAll = toSearchFor.All(x => input.Contains(x));

回答by Jason Hymanson

If you are truly looking to replicate Contains, but for an array, here is an extension methodand sample code for usage:

如果你真的想复制Contains,但对于数组,这里是一个扩展方法和使用示例代码:

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

namespace ContainsAnyThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            string testValue = "123345789";

            //will print true
            Console.WriteLine(testValue.ContainsAny("123", "987", "554")); 

            //but so will this also print true
            Console.WriteLine(testValue.ContainsAny("1", "987", "554"));
            Console.ReadKey();

        }
    }

    public static class StringExtensions
    {
        public static bool ContainsAny(this string str, params string[] values)
        {
            if (!string.IsNullOrEmpty(str) || values.Length > 0)
            {
                foreach (string value in values)
                {
                    if(str.Contains(value))
                        return true;
                }
            }

            return false;
        }
    }
}

回答by justin.m.chase

So am I assuming correctly that uid is a Unique Identifier (Guid)? Is this just an example of a possible scenario or are you really trying to find a guid that matches an array of strings?

那么我是否正确地假设 uid 是唯一标识符(Guid)?这只是可能场景的一个示例,还是您真的想找到与字符串数组匹配的 guid?

If this is true you may want to really rethink this whole approach, this seems like a really bad idea. You should probably be trying to match a Guid to a Guid

如果这是真的,您可能想要真正重新考虑整个方法,这似乎是一个非常糟糕的主意。您可能应该尝试将 Guid 与 Guid 匹配

Guid id = new Guid(uid);
var query = from xx in table
            where xx.uid == id
            select xx;

I honestly can't imagine a scenario where matching a string array using "contains" to the contents of a Guid would be a good idea. For one thing, Contains() will not guarantee the order of numbers in the Guid so you could potentially match multiple items. Not to mention comparing guids this way would be way slower than just doing it directly.

老实说,我无法想象使用“包含”将字符串数组与 Guid 的内容进行匹配会是一个好主意的场景。一方面,Contains() 不会保证 Guid 中数字的顺序,因此您可能会匹配多个项目。更不用说以这种方式比较 guid 会比直接进行要慢得多。

回答by Gorkem Pacaci

You should write it the other way around, checking your priviliged user id list contains the id on that row of table:

您应该反过来写,检查您的特权用户 ID 列表是否包含该表行上的 ID:

string[] search = new string[] { "2", "3" };
var result = from x in xx where search.Contains(x.uid.ToString()) select x;

LINQ behaves quite bright here and converts it to a good SQL statement:

LINQ 在这里表现得非常好,并将其转换为一个好的 SQL 语句:

sp_executesql N'SELECT [t0].[uid]
FROM [dbo].[xx] AS [t0]
WHERE (CONVERT(NVarChar,[t0].[uid]))
IN (@p0, @p1)',N'@p0 nvarchar(1),
@p1 nvarchar(1)',@p0=N'2',@p1=N'3'

which basicly embeds the contents of the 'search' array into the sql query, and does the filtering with 'IN' keyword in SQL.

它基本上将'search'数组的内容嵌入到sql查询中,并在SQL中使用'IN'关键字进行过滤。

回答by Brett Ryan

I managed to find a solution, but not a great one as it requires using AsEnumerable() which is going to return all results from the DB, fortunately I only have 1k records in the table so it isn't really noticable, but here goes.

我设法找到了一个解决方案,但不是一个很好的解决方案,因为它需要使用 AsEnumerable() 它将从数据库中返回所有结果,幸运的是我在表中只有 1k 条记录,所以它并不是很明显,但在这里.

var users = from u in (from u in ctx.Users
                       where u.Mod_Status != "D"
                       select u).AsEnumerable()
            where ar.All(n => u.FullName.IndexOf(n,
                        StringComparison.InvariantCultureIgnoreCase) >= 0)
            select u;


My original post follows:

我的原帖如下:

How do you do the reverse? I want to do something like the following in entity framework.

string[] search = new string[] { "John", "Doe" };
var users = from u in ctx.Users
            from s in search
           where u.FullName.Contains(s)
          select u;

What I want is to find all users where their FullName contains all of the elements in `search'. I've tried a number of different ways, all of which haven't been working for me.

I've also tried

var users = from u in ctx.Users select u;
foreach (string s in search) {
    users = users.Where(u => u.FullName.Contains(s));
}

This version only finds those that contain the last element in the search array.

你如何做相反的事情?我想在实体框架中做类似下面的事情。

string[] search = new string[] { "John", "Doe" };
var users = from u in ctx.Users
            from s in search
           where u.FullName.Contains(s)
          select u;

我想要的是找到他们的全名包含“搜索”中所有元素的所有用户。我尝试了许多不同的方法,但所有方法都不适用于我。

我也试过

var users = from u in ctx.Users select u;
foreach (string s in search) {
    users = users.Where(u => u.FullName.Contains(s));
}

此版本仅查找那些包含搜索数组中最后一个元素的元素。

回答by beauXjames

The best solution I found was to go ahead and create a Table-Valued Function in SQL that produces the results, such as ::

我发现的最佳解决方案是继续在 SQL 中创建一个表值函数来生成结果,例如 ::

CREATE function [dbo].[getMatches](@textStr nvarchar(50)) returns @MatchTbl table(
Fullname nvarchar(50) null,
ID nvarchar(50) null
)
as begin
declare @SearchStr nvarchar(50);
set @SearchStr = '%' + @textStr + '%';
insert into @MatchTbl 
select (LName + ', ' + FName + ' ' + MName) AS FullName, ID = ID from employees where LName like @SearchStr;
return;
end

GO

select * from dbo.getMatches('j')

Then, you simply drag the function into your LINQ.dbml designer and call it like you do your other objects. The LINQ even knows the columns of your stored function. I call it out like this ::

然后,您只需将该函数拖入您的 LINQ.dbml 设计器并像调用其他对象一样调用它。LINQ 甚至知道存储函数的列。我这样称呼它::

Dim db As New NobleLINQ
Dim LNameSearch As String = txt_searchLName.Text
Dim hlink As HyperLink

For Each ee In db.getMatches(LNameSearch)
   hlink = New HyperLink With {.Text = ee.Fullname & "<br />", .NavigateUrl = "?ID=" & ee.ID}
   pnl_results.Controls.Add(hlink)
Next

Incredibly simple and really utlizes the power of SQL and LINQ in the application...and you can, of course, generate any table valued function you want for the same effects!

难以置信的简单并且真正在应用程序中充分利用了 SQL 和 LINQ 的强大功能……当然,您可以生成您想要的任何表值函数以获得相同的效果!