Как использовать LINQ Contains (string []) вместо Contains (string)

У меня появился один большой вопрос.

Я получил запрос linq, чтобы он выглядел следующим образом:

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

Значения массива string[] будут такими цифрами, как (1,45,20,10 и т.д.)

Значение по умолчанию для .Contains равно .Contains(string).

Мне нужно это сделать вместо этого: .Contains(string[])...

EDIT: Один пользователь предложил написать класс расширения для string[]. Я хотел бы узнать, как, но кто-то хочет указать мне в правильном направлении?

EDIT:. uid также будет числом. Вот почему он преобразуется в строку.

Помогите кому-нибудь?

Ответ 1

spoulson имеет почти прав, но сначала вам нужно создать List<string> от string[]. На самом деле a List<int> было бы лучше, если uid также int. List<T> поддерживает Contains(). Выполнение uid.ToString().Contains(string[]) означает, что uid как строка содержит все значения массива в качестве подстроки??? Даже если бы вы написали метод расширения, смысл этого был бы неправильным.

[EDIT]

Если вы не изменили его и не написали на string[], как демонстрирует Митч Пшеница, вы просто сможете пропустить шаг преобразования.

[ENDEDIT]

Вот что вы хотите, если вы не используете метод расширения (если у вас уже нет коллекции потенциальных uids как ints), тогда просто используйте List<int>()). В этом случае используется синтаксис с цепочкой, который, по моему мнению, более чист, и делает преобразование в int, чтобы гарантировать, что запрос может использоваться с большим количеством поставщиков.

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

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

Ответ 2

Если вы действительно хотите реплицировать 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;
        }
    }
}

Ответ 3

Попробуйте следующее.

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

Ответ 4

LINQ в .NET 4.0 имеет для вас еще один вариант; метод .Any();

string[] values = new[] { "1", "2", "3" };
string data = "some string 1";
bool containsAny = values.Any(data.Contains);

Ответ 5

Или, если у вас уже есть данные в списке и предпочитаете другой формат Linq:)

List<string> uids = new List<string>(){"1", "45", "20", "10"};
List<user> table = GetDataFromSomewhere();

List<user> newTable = table.Where(xx => uids.Contains(xx.uid)).ToList();

Ответ 6

Как насчет:

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

Ответ 7

Это пример одного из способов написания метода расширения (примечание: я бы не использовал его для очень больших массивов, а другая структура данных была бы более подходящей...):

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

Ответ 8

Это поздний ответ, но я считаю, что он по-прежнему полезен. Я создал пакет NinjaNye.SearchExtension nuget, который может помочь решить эту проблему.:

string[] terms = new[]{"search", "term", "collection"};
var result = context.Table.Search(terms, x => x.Name);

Вы также можете выполнить поиск нескольких свойств строки

var result = context.Table.Search(terms, x => x.Name, p.Description);

Или выполните RankedSearch, который возвращает IQueryable<IRanked<T>>, который просто включает свойство, которое показывает, сколько раз появлялись поисковые запросы:

//Perform search and rank results by the most hits
var result = context.Table.RankedSearch(terms, x => x.Name, x.Description)
                     .OrderByDescending(r = r.Hits);

Существует более подробное руководство по проектам страницы GitHub: https://github.com/ninjanye/SearchExtensions

Надеюсь, это поможет будущим посетителям.

Ответ 9

Я считаю, что вы также можете сделать что-то вроде этого.

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

Ответ 10

Метод расширения Linq. Будет работать с любым IEnumerable объектом:

    public static bool ContainsAny<T>(this IEnumerable<T> Collection, IEnumerable<T> Values)
    {
        return Collection.Any(x=> Values.Contains(x));
    }

Использование:

string[] Array1 = {"1", "2"};
string[] Array2 = {"2", "4"};

bool Array2ItemsInArray1 = List1.ContainsAny(List2);

Ответ 11

Я правильно понял, что uid - это уникальный идентификатор (Guid)? Это просто пример возможного сценария или вы действительно пытаетесь найти руководство, которое соответствует массиву строк?

Если это правда, вы можете действительно переосмыслить весь этот подход, это кажется очень плохой идеей. Вероятно, вам следует попытаться сопоставить "Руководство к руководству"

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

Я, честно говоря, не могу представить сценарий, когда совмещение массива строк с использованием "содержит" к содержанию Guid было бы хорошей идеей. Во-первых, Contains() не гарантирует порядок номеров в Guid, чтобы вы могли сопоставить несколько элементов. Не говоря уже о том, что сравнение гидов таким образом было бы медленнее, чем просто делать это напрямую.

Ответ 12

Вы должны написать это по-другому, проверяя, что ваш привилегированный список идентификаторов пользователей содержит идентификатор в этой строке таблицы:

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

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'

который в основном встраивает содержимое массива "поиск" в запрос sql и выполняет фильтрацию с ключевым словом "IN" в SQL.

Ответ 13

Мне удалось найти решение, но не очень хорошее, так как для этого нужно использовать 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;

Мой исходный пост:

Как вы делаете обратное? я хочу сделать что-то вроде следующего в сущность.

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

Я хочу найти всех пользователей, где их FullName содержит все элементов в "поиске". Я пробовал количество разных способов, все из которых не работали для меня.

Я также пробовал

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

В этой версии найдены только те, которые содержать последний элемент в поиске массив.

Ответ 14

Лучшее решение, которое я нашел, заключалось в том, чтобы продолжить работу над табличной функцией в 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')

Затем вы просто перетаскиваете функцию в свой дизайнер 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

Невероятно простой и действительно применяющий мощь SQL и LINQ в приложении... и вы, конечно же, можете генерировать любую функцию, которая вам нужна для тех же самых эффектов!

Ответ 15

Я считаю, что вы действительно хотите: предположим сценарий у вас есть две базы данных и у них есть таблица общих продуктов И вы хотите выбрать продукты из таблицы "A", которые имеют общий идентификатор с "B"

используя этот метод, будет слишком сложно сделать это то, что мы делаем, является пересечением, и существует метод, называемый пересечением для этого

пример из msdn: http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1

int [] numbers = (0, 2, 4, 5, 6, 8, 9); int [] numbersB = (1, 3, 5, 7, 8); var = commonNumbers numbersA.Intersect(numbersB);

Я думаю, что вам нужно легко решить с помощью пересечения

Ответ 16

from xx in table
where xx.uid.Split(',').Contains(string value )
select xx

Ответ 17

Проверьте этот метод расширения:

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

namespace ContainsAnyProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            const string iphoneAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like...";

            var majorAgents = new[] { "iPhone", "Android", "iPad" };
            var minorAgents = new[] { "Blackberry", "Windows Phone" };

            // true
            Console.WriteLine(iphoneAgent.ContainsAny(majorAgents));

            // false
            Console.WriteLine(iphoneAgent.ContainsAny(minorAgents));
            Console.ReadKey();
        }
    }

    public static class StringExtensions
    {
        /// <summary>
        /// Replicates Contains but for an array
        /// </summary>
        /// <param name="str">The string.</param>
        /// <param name="values">The values.</param>
        /// <returns></returns>
        public static bool ContainsAny(this string str, params string[] values)
        {
            if (!string.IsNullOrEmpty(str) && values.Length > 0)
                return values.Any(str.Contains);

            return false;
        }
    }
}

Ответ 18

Try:

var stringInput = "test";
var listOfNames = GetNames();
var result = from names in listOfNames where names.firstName.Trim().ToLower().Contains(stringInput.Trim().ToLower());
select names;

Ответ 19

string[] stringArray = {1,45,20,10};
from xx in table 
where stringArray.Contains(xx.uid.ToString()) 
select xx

Ответ 20

Dim stringArray() = {"Pink Floyd", "AC/DC"}
Dim inSQL = From alb In albums Where stringArray.Contains(alb.Field(Of String)("Artiste").ToString())
Select New With
  {
     .Album = alb.Field(Of String)("Album"),
     .Annee = StrReverse(alb.Field(Of Integer)("Annee").ToString()) 
  }