Как использовать 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 также будет числом. Вот почему он преобразуется в строку.



кому-то помогает?

626   20  

20 ответов:

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

Если вы действительно хотите повторить содержит, но для массива, вот это метод расширения и пример кода для использования:

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

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

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

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

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

или если у вас уже есть данные в списке и вы предпочитаете другой формат 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();

Как насчет:

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

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

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

это поздний ответ, но я считаю, что это все еще полезно.
Я создал 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

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

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

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

метод расширения 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);

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

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

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

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

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

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.

мне удалось найти решение, но не великое, поскольку оно требует использования 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;

мой оригинальный пост следующим образом:

как вы делаете обратное? Я хочу сделайте что-то вроде следующего платформа 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;

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

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

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

эта версия находит только те, что содержит последний элемент в поиске матрица.

лучшее решение, которое я нашел, состояло в том, чтобы пойти дальше и создать возвращающую табличное значение функцию в 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 designer и назовите его, как вы делаете ваши другие объекты. В 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

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

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

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

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

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

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

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

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;
        }
    }
}
from xx in table
where xx.uid.Split(',').Contains(string value )
select xx

попробуй:

var stringInput = "test";
var listOfNames = GetNames();
var result = from names in listOfNames where names.firstName.Trim().ToLower().Contains(stringInput.Trim().ToLower());
select names;
string[] stringArray = {1,45,20,10};
from xx in table 
where stringArray.Contains(xx.uid.ToString()) 
select xx
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()) 
  }

Comments

    Ничего не найдено.