मैं युक्तियों (स्ट्रिंग) के बजाय LINQ युक्तियों (स्ट्रिंग []) का उपयोग कैसे करूं


103

मुझे एक बड़ा सवाल मिला।

मुझे एक 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[]। मैं सीखना चाहूंगा कि कैसे, लेकिन कोई भी मुझे सही दिशा में इंगित करने के लिए तैयार है?

संपादित करें: यूआईडी भी एक संख्या होगी। इसलिए इसे स्ट्रिंग में परिवर्तित किया जाता है।

किसी की मदद करो?


आपको यह स्पष्ट करने की आवश्यकता है कि एक यूआईडी जैसा दिख सकता है, और जिसे मैच माना जाएगा।
जेम्स कुर्रान

3
एक उदाहरण अच्छा होगा। यह मुझे लगता है जैसे सवाल यूआईडी के लिए पूछ रहा है जैसे: CA1FAB689C33 और सरणी: {"42", "2259", "सीए"}
थॉमस ब्राट

3
विपरीत अर्थ अधिक समझ में आता है: स्ट्रिंग []। सम्‍मिलित (xx.uid)
मेजकिनटॉर

जवाबों:


86

स्पूल्सन के पास यह लगभग सही है, लेकिन आपको पहले List<string>से बनाने की आवश्यकता है string[]। वास्तव में एक List<int>बेहतर होगा यदि uid भी है intList<T>समर्थन करता है Contains()। कर रहे uid.ToString().Contains(string[])हैं कि एक स्ट्रिंग के रूप में uid एक विकल्प के रूप में सरणी के सभी मूल्यों में शामिल होगा ??? यदि आपने विस्तार विधि लिखी है तो भी इसका अर्थ गलत होगा।

[संपादित करें]

जब तक आपने इसे इधर-उधर नहीं बदला और इसे string[]मिच गेहूं के रूप में प्रदर्शित किया, तब तक आप रूपांतरण चरण को छोड़ सकेंगे।

[ENDEDIT]

यहाँ आप क्या चाहते हैं, यदि आप विस्तार विधि नहीं करते हैं (जब तक कि आपके पास पहले से ही स्याही के रूप में संभावित uids का संग्रह नहीं है - तो List<int>()इसके बजाय बस )। यह जंजीर पद्धति सिंटैक्स का उपयोग करता है, जो मुझे लगता है कि क्लीनर है, और यह सुनिश्चित करने के लिए रूपांतरण का उपयोग करता है कि क्वेरी का उपयोग अधिक प्रदाताओं के साथ किया जा सकता है।

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

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

धन्यवाद। यह सही उत्तर था ... एक और विचार? चलो कहते हैं कि arrayuids भी एक linq क्वेरी है। किसी भी तरह से आप डेटाबेस से सिर्फ एक क्वेरी के लिए दोनों बयान प्राप्त कर सकते हैं?
SpoiledTechie.com

4
MSDN के अनुसार, स्ट्रिंग [] औजार IEnumerable <T>, जिसमें एक कंटेंस्ट विधि है। इसलिए, सरणी को IList <T> में बदलना आवश्यक नहीं है। msdn.microsoft.com/en-us/library/19e6zeyy.aspx
spoulson

अंतिम .ToString () मेरे लिए त्रुटियाँ फेंकता है। विशेष रूप से, LINQ to Entities विधि 'System.String ToString ()' विधि को नहीं पहचानता है, और इस पद्धति को स्टोर एक्सप्रेशन में अनुवादित नहीं किया जा सकता है .... इसे हटाने के बाद, लैम्ब्डा ने मेरे लिए काम किया।
सैम स्टैग

मुझे यह पसंद है, यह इतना आसान है कि मुझे यह याद नहीं है।
ओलाज

@SamStange - LINQ के साथ एक समस्या यह है कि बहुत सारे वेरिएंट हैं और एब्सट्रैक्शन "लीक" है, आपको कभी-कभी यह जानना होगा कि क्वेरी को ठीक से बनाने के लिए आप किस वेरिएंट का उपयोग कर रहे हैं। जैसा कि लिखा गया है कि यह LINQ से ऑब्जेक्ट्स तक काम करेगा (और LINQ to SQL हो सकता है)। EF के लिए, आप इसे दूसरे तरीके से करेंगे List<int>और इसके बजाय मेमोरी में संग्रह का निर्माण करेंगे और ToStringकॉल को छोड़ देंगे ।
tvanfosson

36

यदि आप वास्तव में 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;
        }
    }
}

2
+1 @ जैसन, आपको इसे पूरी तरह से ExtensionMethod.net पर सबमिट करना चाहिए । महान कोड के लिए धन्यवाद, इसने आज मेरी समस्या हल कर दी!
पी। काम्पबेल

4
मुझे लगता है कि आप का मतलब है! स्ट्रिंग .sNullOrEmpty (str) और& मानों। चल> 0
ग्रेग बोगुमिल

तुम सही हो। मैंने इसे बदल दिया, हालांकि इसका कार्यात्मक प्रभाव नहीं है। मैं काम पर इस तरह के एक समारोह का उपयोग करें। मुझे इसकी जाँच करनी होगी!
जेसन जैक्सन

@JasonJackson मुझे एहसास है कि यह पुरानी (ish) है, लेकिन (जैसा कि ग्रेग ने उल्लेख किया है) क्या आप उस सशर्त में "या" नहीं बल्कि "और" चाहते हैं?
टायसन टी।

@TiesonT। दोनों "या फिर" और "और" भी सशर्त एक ही परिणाम के साथ समाप्त हो जाएंगे; यदि !string.IsNullOrEmpty(str)चेक पास हो गया, जिससे values.Length > 0स्थिति को नजरअंदाज कर दिया गया, लेकिन मानों की लंबाई 0 थी , तो यह तब तक चला जाएगा foreachऔर फिर तुरंत टूट जाएगा क्योंकि सरणी में कोई प्रविष्टि नहीं है, सीधे पर जा रहा है return false
मेवमोरिटस

20

निम्नलिखित का प्रयास करें।

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

2
मैं वास्तव में चाहता हूं कि लोग एक टिप्पणी छोड़ दें जब वे आपको चिह्नित करेंगे। खासकर जब से मैंने उत्तर दिया है, 100% सही है।
जारेदपार

यह मैं नहीं था, लेकिन सभी () केवल एक बूल का संकेत नहीं देते हैं जहां सभी आइटम स्थिति से मेल खाते हैं? और NullReferenceException की गारंटी के लिए toSearchFor को प्रारंभ करना।
लुकास

मैंने अशक्त मुद्दे को टाइप करने के लिए तैयार किया। सभी पर हाँ। यह प्रभावी रूप से सुनिश्चित करता है कि इनसर्चफॉर में सभी तार इनपुट स्ट्रिंग के भीतर समाहित हैं।
जेरदपार

6
मैं यह नहीं देखता कि यह सवाल का जवाब कैसे देता है। क्या आप पर सवाल उठ गया?
tvanfosson

15

.NET 4.0 में LINQ आपके लिए एक और विकल्प है; .Any () विधि;

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

1
शानदार उत्तर, अभिव्यक्ति Any()और All()तरीके बहुत सरल हैं :) मैं उपयोग कर सकता हूं t => words.All(w => t.Title.Contains(w))
शराब बुराई है

7

या यदि आपके पास पहले से ही एक सूची में डेटा है और अन्य 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();

3

कैसा रहेगा:

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

NotSupportedException: तुलना ऑपरेटर 'System.String []' प्रकार के लिए समर्थित नहीं है, लेकिन फिर से प्रयास करें?
SpoiledTechie.com

+1, यदि यह वास्तव में वही है जो वे चाहते हैं। यह सवाल से बहुत स्पष्ट नहीं है।
लुकास

2

यह विस्तार विधि लिखने के एक तरीके का एक उदाहरण है (नोट: मैं इसका उपयोग बहुत बड़ी सरणियों के लिए नहीं करूंगा; एक अन्य डेटा संरचना अधिक उपयुक्त होगी ...):

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

1
यह सार्वजनिक स्टेटिक बूल कंटेस्टेंट्स के समान होगा (यह स्ट्रिंग [] stringarray, string pat) {वापसी Array.IndexOf (stringarray, pat)! = -1; }
जेम्स कुर्रन

5
स्ट्रिंग [] लागू करता है IEnumerable <string>, इसलिए इसमें पहले से ही एक Contains (स्ट्रिंग) एक्सटेंशन विधि है। हम इसे क्यों लागू कर रहे हैं?
लुकास

2

यह एक देर से जवाब है, लेकिन मेरा मानना ​​है कि यह अभी भी उपयोगी है
मैंने 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

आशा है कि यह भविष्य के आगंतुकों को मदद करेगा


1
हां, इसे विशेष रूप से एंटिटी फ्रेमवर्क को लक्षित करने के लिए बनाया गया है
निंजाएन

1
क्या मैं इसके साथ .Where () पद्धति का उपयोग कर सकता हूं?
हमजा खानजादा

हाँ, यह काम करता है IQueryableऔर IEnumerable- बस दूर रहो कि अगर आप इसे एक IEnumerable श्रृंखला से दूर करते हैं, तो यह एक क्वेरी बनाने और स्रोत को नीचे भेजने के बजाय
मेमोरियरी में चलेगा

2

लाइनक विस्तार विधि। किसी भी 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);

1

मेरा मानना ​​है कि आप भी कुछ ऐसा कर सकते हैं।

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

उसी के रूप में "जहां stringArray.Contains (xx.uid.ToString ())", इसे क्वेरी में इधर-उधर लपेटने की आवश्यकता नहीं है
लुकास

0

तो क्या मैं सही तरीके से मान रहा हूं कि यूआईडी एक यूनीक आइडेंटिफायर (गाइड) है? क्या यह केवल एक संभावित परिदृश्य का एक उदाहरण है या क्या आप वास्तव में एक ऐसे मार्गदर्शक को खोजने की कोशिश कर रहे हैं जो तार की एक सरणी से मेल खाता हो?

यदि यह सच है तो आप वास्तव में इस पूरे दृष्टिकोण पर फिर से विचार कर सकते हैं, यह एक बहुत बुरा विचार है। आपको शायद एक गाइड से एक गाइड से मेल खाने की कोशिश करनी चाहिए

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

मैं ईमानदारी से एक परिदृश्य की कल्पना नहीं कर सकता, जहां एक गाइड की सामग्री के लिए "समाहित" का उपयोग करके एक स्ट्रिंग सरणी का मिलान करना एक अच्छा विचार होगा। एक बात के लिए, Contains () गाइड में संख्याओं के क्रम की गारंटी नहीं देगा, ताकि आप संभावित रूप से कई वस्तुओं का मिलान कर सकें। इस तरह से तुलना करने का उल्लेख नहीं करने के लिए इस तरह से यह सिर्फ सीधे कर से धीमी होगी।


0

आपको इसे दूसरे तरीके से लिखना चाहिए, अपने प्राइवेटलाइज्ड यूजर आईडी लिस्ट को चेक करने के लिए आईडी को उस पंक्ति में रखना चाहिए:

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 क्वेरी में एम्बेड करता है, और SQL में 'IN' कीवर्ड के साथ फ़िल्टरिंग करता है।


यह तब तक ठीक काम करता है जब तक आपके पास 2100 से अधिक पैरामीटर न हों।
जिपरसन

0

मैं एक समाधान खोजने में कामयाब रहा, लेकिन एक महान के रूप में इसे असेंबल () का उपयोग करने की आवश्यकता नहीं है जो डीबी से सभी परिणाम वापस करने जा रहा है, सौभाग्य से मेरे पास तालिका में केवल 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));
}

यह संस्करण केवल उन्हीं को खोजता है जिनमें खोज एरे में अंतिम तत्व होता है।


0

मुझे जो सबसे अच्छा समाधान मिला वह था आगे बढ़ना और SQL में Table-Valued Function बनाना जो परिणाम उत्पन्न करता है, जैसे ::

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 की शक्ति को इंगित करता है ... और आप निश्चित रूप से, किसी भी तालिका मूल्यवान फ़ंक्शन को उत्पन्न कर सकते हैं जो आप उसी प्रभाव के लिए चाहते हैं!


0

मेरा मानना ​​है कि आप वास्तव में क्या करना चाहते हैं: आइए एक ऐसे परिदृश्य की कल्पना करें जिसके आपके पास दो डेटाबेस हैं और उनके पास आम में उत्पादों की एक तालिका है और आप तालिका "ए" से उत्पादों का चयन करना चाहते हैं जो कि आईडी में "बी" के साथ आम है।

विधि का उपयोग करना बहुत जटिल होगा ऐसा करने के लिए हम जो कर रहे हैं वह एक चौराहा है, और इसके लिए एक विधि है जिसे प्रतिच्छेदन कहा जाता है

msdn का एक उदाहरण: http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1

int [] संख्या = (0, 2, 4, 5, 6, 8, 9); int [] नंबरबी = (1, 3, 5, 7, 8); var = commonNumbers numbersA.Intersect (नंबरबी);

मुझे लगता है कि चौराहे के साथ आपको जो चाहिए वह आसानी से हल हो जाएगा


0

इस विस्तार विधि की जाँच करें:

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


0

प्रयत्न:

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

इस कोड को इस सवाल का जवाब कर सकते हैं, के बारे में अतिरिक्त संदर्भ प्रदान करने के लिए कैसे और / या क्यों यह हल करती है समस्या जवाब की दीर्घकालिक मूल्य में सुधार होगा।
फ्रांसेस्को मेंजानी 15

0
var SelecetdSteps = Context.FFTrakingSubCriticalSteps
             .Where(x => x.MeetingId == meetid)
             .Select(x =>    
         x.StepID  
             );

        var crtiticalsteps = Context.MT_CriticalSteps.Where(x =>x.cropid==FFT.Cropid).Select(x=>new
        {
            StepID= x.crsid,
            x.Name,
            Checked=false

        });


        var quer = from ax in crtiticalsteps
                   where (!SelecetdSteps.Contains(ax.StepID))
                   select ax;

0
        string texto = "CALCA 40";
        string[] descpart = texto.Split(' ');

        var lst = (from item in db.InvItemsMaster
                   where descpart.All(val => item.itm_desc.Contains(val))
                   select item
                    ).ToList();
        Console.WriteLine("ITM".PadRight(10) + "DESC".PadRight(50)+"EAN".PadRight(14));
        foreach(var i in lst)
        {
           

            Console.Write(i.itm_id.ToString().PadRight(10));
            Console.Write(i.itm_desc.ToString().PadRight(50));
            Console.WriteLine(i.itm_ean.ToString().PadRight(14));


        }

        Console.ReadKey();

हम, एसओ के पास आते हैं। कृपया "कोड केवल" उत्तर न दें। क्या आप कुछ स्पष्टीकरण जोड़ सकते हैं कि यह समस्या को कैसे हल करता है और पहले से ही अन्य 21 उत्तरों द्वारा कवर नहीं किया गया है?
मार्श-विगल

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

-2
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()) 
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.