C# Language
LINQ Queries
खोज…
परिचय
LINQ एक संक्षिप्त जो tegrated क्यू uery में एल anguage के लिए खड़ा है। यह एक अवधारणा है जो विभिन्न प्रकार के डेटा स्रोतों और प्रारूपों में डेटा के साथ काम करने के लिए एक सुसंगत मॉडल की पेशकश करके एक क्वेरी भाषा को एकीकृत करता है; आप XML दस्तावेज़ों, SQL डेटाबेस, ADO.NET डेटासेट्स, .NET संग्रह और डेटा के लिए एक ही मूल कोडिंग पैटर्न का उपयोग करते हैं और जिसके लिए LINQ प्रदाता उपलब्ध है।
वाक्य - विन्यास
क्वेरी सिंटैक्स:
- <रेंज वेरिएबल> से <संग्रह> में
- [से <संग्रह चर> में <संग्रह>, ...]
- <फ़िल्टर, ज्वाइनिंग, ग्रुपिंग, एग्रीगेट ऑपरेटर, ...> <लैम्ब्डा एक्सप्रेशन>
- <select or groupBy ऑपरेटर> <परिणाम तैयार करें>
विधि सिंटैक्स:
- Enumerable.Aggregate (समारोह)
- Enumerable.Aggregate (बीज, दुर्गंध)
- Enumerable.Aggregate (बीज, कवक, परिणामक)
- Enumerable.All (विधेय)
- Enumerable.Any ()
- Enumerable.Any (विधेय)
- Enumerable.AsEnumerable ()
- Enumerable.Average ()
- Enumerable.Average (चयनकर्ता)
- Enumerable.Cast <परिणाम> ()
- Enumerable.Concat (दूसरा)
- Enumerable.Contains (मान)
- Enumerable.Contains (मान, तुलना)
- Enumerable.Count ()
- Enumerable.Count (विधेय)
- Enumerable.DefaultIfEmpty ()
- Enumerable.DefaultIfEmpty (DefaultValue)
- Enumerable.Distinct ()
- Enumerable.Distinct (comparer)
- Enumerable.ElementAt (इंडेक्स)
- Enumerable.ElementAtOrDefault (इंडेक्स)
- Enumerable.Empty ()
- Enumerable.Except (दूसरा)
- Enumerable.Except (दूसरा, तुलना)
- Enumerable.First ()
- Enumerable.First (विधेय)
- Enumerable.FirstOrDefault ()
- Enumerable.FirstOrDefault (विधेय)
- Enumerable.GroupBy (keySelector)
- Enumerable.GroupBy (keySelector, resultSelector)
- Enumerable.GroupBy (keySelector, elementSelector)
- Enumerable.GroupBy (keySelector, तुलनित्र)
- Enumerable.GroupBy (keySelector, resultSelector, तुलनित्र)
- Enumerable.GroupBy (keySelector, elementSelector, resultSelector)
- Enumerable.GroupBy (keySelector, elementSelector, तुलनित्र)
- Enumerable.GroupBy (keySelector, elementSelector, resultSelector, तुलनित्र)
- Enumerable.Intersect (दूसरा)
- Enumerable.Intersect (दूसरा, तुलना)
- Enumerable.Join (इनर, आउटरकेयलेक्टर, इनरकेयलेक्टर, रिजल्ट सेटर)
- Enumerable.Join (इनर, आउटरकेयलेक्टर, इनरकेयलेक्टर, रिजल्टसेंटर, तुलनित्र)
- Enumerable.Last ()
- Enumerable.Last (विधेय)
- Enumerable.LastOrDefault ()
- Enumerable.LastOrDefault (विधेय)
- Enumerable.LongCount ()
- Enumerable.LongCount (विधेय)
- Enumerable.Max ()
- Enumerable.Max (चयनकर्ता)
- Enumerable.Min ()
- Enumerable.Min (चयनकर्ता)
- Enumerable.OfType <TResult> ()
- Enumerable.OrderBy (keySelector)
- Enumerable.OrderBy (keySelector, तुलनित्र)
- Enumerable.OrderByDescending (keySelector)
- Enumerable.OrderByDescending (की-सेक्टर, तुलनित्र)
- Enumerable.Range (शुरू, गिनती)
- Enumerable.Repeat (तत्व, गणना)
- Enumerable.Reverse ()
- Enumerable.Select (चयनकर्ता)
- Enumerable.SelectMany (चयनकर्ता)
- Enumerable.SelectMany (संग्रहकार्यकर्ता, परिणामकर्ता)
- Enumerable.SequenceEqual (दूसरा)
- Enumerable.SequenceEqual (दूसरा, तुलना)
- Enumerable.Single ()
- Enumerable.Single (विधेय)
- Enumerable.SingleOrDefault ()
- Enumerable.SingleOrDefault (विधेय)
- Enumerable.Skip (संख्या)
- Enumerable.SkipWhile (विधेय)
- Enumerable.Sum ()
- Enumerable.Sum (चयनकर्ता)
- Enumerable.Take (संख्या)
- Enumerable.TakeWhile (विधेय)
- orderedEnumerable.ThenBy (keySelector)
- orderEnumerable.ThenBy (keySelector, तुलनित्र)
- orderedEnumerable.ThenByDescending (keySelector)
- आदेश दिया गया। ThenByDescending (keySelector, तुलनित्र)
- Enumerable.ToArray ()
- Enumerable.ToDictionary (keySelector)
- Enumerable.ToDictionary (keySelector, elementSelector)
- Enumerable.ToDictionary (keySelector, तुलनित्र)
- Enumerable.ToDictionary (keySelector, elementSelector, तुलनित्र)
- Enumerable.ToList ()
- Enumerable.ToLookup (keySelector)
- Enumerable.ToLookup (KeySelector, elementSelector)
- Enumerable.ToLookup (keySelector, तुलनित्र)
- Enumerable.ToLookup (keySelector, elementSelector, तुलनित्र)
- Enumerable.Union (दूसरा)
- Enumerable.Union (दूसरा, तुलना)
- Enumerable.Where (विधेय)
- Enumerable.Zip (दूसरा, परिणामकर्ता)
टिप्पणियों
LINQ प्रश्नों का उपयोग करने के लिए आपको System.Linq
को आयात करना होगा।
विधि सिंटैक्स अधिक शक्तिशाली और लचीला है, लेकिन क्वेरी सिंटैक्स सरल और अधिक परिचित हो सकता है। क्वेरी सिंटैक्स में लिखे गए सभी प्रश्नों को कंपाइलर द्वारा कार्यात्मक सिंटैक्स में अनुवादित किया जाता है, इसलिए प्रदर्शन समान है।
जब तक उनका उपयोग नहीं किया जाता है, तब तक क्वेरी ऑब्जेक्ट का मूल्यांकन नहीं किया जाता है, इसलिए उन्हें प्रदर्शन दंड के बिना बदला या जोड़ा जा सकता है।
कहाँ पे
उन मदों का एक सबसेट लौटाता है जो निर्दिष्ट विधेय उनके लिए सत्य है।
List<string> trees = new List<string>{ "Oak", "Birch", "Beech", "Elm", "Hazel", "Maple" };
विधि सिंटैक्स
// Select all trees with name of length 3
var shortTrees = trees.Where(tree => tree.Length == 3); // Oak, Elm
क्वेरी सिंटैक्स
var shortTrees = from tree in trees
where tree.Length == 3
select tree; // Oak, Elm
चयन करें - रूपांतरणकारी तत्व
चयन करें आपको IEnumerable को लागू करने वाले किसी भी डेटा संरचना में हर तत्व में परिवर्तन लागू करने की अनुमति देता है।
निम्नलिखित सूची में प्रत्येक स्ट्रिंग का पहला वर्ण प्राप्त करना:
List<String> trees = new List<String>{ "Oak", "Birch", "Beech", "Elm", "Hazel", "Maple" };
नियमित (लंबोदर) वाक्य रचना का उपयोग करना
//The below select stament transforms each element in tree into its first character.
IEnumerable<String> initials = trees.Select(tree => tree.Substring(0, 1));
foreach (String initial in initials) {
System.Console.WriteLine(initial);
}
आउटपुट:
हे
बी
बी
इ
एच
म
LINQ क्वेरी सिंटैक्स का उपयोग करना
initials = from tree in trees
select tree.Substring(0, 1);
जंजीर बनाने के तरीके
कई LINQ कार्यों दोनों एक पर काम IEnumerable<TSource>
और यह भी एक वापसी IEnumerable<TResult>
। TSource
और TResult
प्रकार के पैरामीटर उसी प्रकार को संदर्भित कर सकते हैं या नहीं कर सकते हैं, जो प्रश्न में विधि के आधार पर हो सकता है और इसके लिए कोई फ़ंक्शंस।
इसके कुछ उदाहरण हैं
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector
)
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, int, bool> predicate
)
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
चूँकि कुछ विधि को पूरा करने के लिए एक पूरे सेट की आवश्यकता होती है, जिस पर आगे बढ़ने से पहले LINQ उपज रिटर्न MSDN का उपयोग करके आस्थगित निष्पादन का लाभ उठाता है जो दृश्यों के पीछे एक Enumerable और Enumerator बनाता है। LINQ में chaining की प्रक्रिया मूल रूप से मूल सेट के लिए एक गणना योग्य (पुनरावृत्ति) का निर्माण कर रही है - जो कि आस्थगित है - जब तक कि गणना करने वाले को enumerating द्वारा भौतिक नहीं किया जाता है।
यह इन कार्यों को तेजी से जंजीर विकी की अनुमति देता है, जहां एक फ़ंक्शन दूसरे के परिणाम पर सीधे कार्य कर सकता है। एक ही कथन में कई अनुक्रम आधारित संचालन करने के लिए कोड की इस शैली का उपयोग किया जा सकता है।
उदाहरण के लिए, एकल विवरण में अनुक्रम को रूपांतरित, फ़िल्टर और क्रमबद्ध करने के लिए Select
, Where
और OrderBy
को संयोजित करना संभव है।
var someNumbers = { 4, 3, 2, 1 };
var processed = someNumbers
.Select(n => n * 2) // Multiply each number by 2
.Where(n => n != 6) // Keep all the results, except for 6
.OrderBy(n => n); // Sort in ascending order
आउटपुट:
2
4
8
कोई भी फ़ंक्शन जो सामान्य IEnumerable<T>
प्रकार दोनों का विस्तार करता है और वापस करता है, एक ही कथन में जंजीर खंड के रूप में उपयोग किया जा सकता है। धाराप्रवाह प्रोग्रामिंग की यह शैली शक्तिशाली है, और अपने स्वयं के विस्तार के तरीकों का निर्माण करते समय विचार किया जाना चाहिए।
रेंज और रिपीट
Enumerable
पर Range
और Repeat
स्टेटिक विधियों का उपयोग सरल अनुक्रम उत्पन्न करने के लिए किया जा सकता है।
रेंज
Enumerable.Range()
एक आरंभिक मूल्य और एक गिनती दिए गए पूर्णांकों का एक क्रम उत्पन्न करता है।
// Generate a collection containing the numbers 1-100 ([1, 2, 3, ..., 98, 99, 100])
var range = Enumerable.Range(1,100);
दोहराना
Enumerable.Repeat()
एक तत्व दिए गए दोहराए जाने वाले तत्वों और आवश्यक दोहराव की संख्या का एक क्रम उत्पन्न करता है।
// Generate a collection containing "a", three times (["a","a","a"])
var repeatedValues = Enumerable.Repeat("a", 3);
छोड़ो और लो
छोड़ें विधि स्रोत संग्रह की शुरुआत से कई मदों को छोड़कर एक संग्रह लौटाता है। बहिष्कृत वस्तुओं की संख्या एक तर्क के रूप में दी गई संख्या है। यदि तर्क में निर्दिष्ट से कम संग्रह में आइटम हैं तो एक खाली संग्रह लौटाया जाता है।
स्रोत संग्रह की शुरुआत से ले विधि कई तत्वों से युक्त संग्रह लौटाती है। शामिल मदों की संख्या एक तर्क के रूप में दी गई संख्या है। यदि तर्क में निर्दिष्ट की तुलना में संग्रह में कम आइटम हैं तो लौटाए गए संग्रह में स्रोत संग्रह के समान तत्व होंगे।
var values = new [] { 5, 4, 3, 2, 1 };
var skipTwo = values.Skip(2); // { 3, 2, 1 }
var takeThree = values.Take(3); // { 5, 4, 3 }
var skipOneTakeTwo = values.Skip(1).Take(2); // { 4, 3 }
var takeZero = values.Take(0); // An IEnumerable<int> with 0 items
उदाहरण के लिए, पगेट परिणाम के लिए स्किप और टेक का एक साथ उपयोग किया जाता है:
IEnumerable<T> GetPage<T>(IEnumerable<T> collection, int pageNumber, int resultsPerPage) {
int startIndex = (pageNumber - 1) * resultsPerPage;
return collection.Skip(startIndex).Take(resultsPerPage);
}
चेतावनी: LINQ से एंटिटीज़ केवल ऑर्डर किए गए प्रश्नों पर स्किप का समर्थन करती हैं। यदि आप आदेश का उपयोग किए बिना छोड़ें का उपयोग करने का प्रयास करते हैं, तो आपको संदेश के साथ एक NotSupportedException मिलेगी "विधि छोड़ें 'केवल LINQ में प्रविष्टियों के लिए सॉर्ट किए गए इनपुट के लिए समर्थित है। विधि' OrderBy 'को विधि' Skip 'से पहले बुलाया जाना चाहिए।"
पहला, फर्स्टऑडफॉल्ट, लास्ट, लास्टऑर्डीफॉल्ट, सिंगल और सिंगलऑर्डीफॉल्ट
सभी छह विधियाँ अनुक्रम प्रकार का एक ही मान लौटाती हैं, और उन्हें विधेय के साथ या बिना कहा जा सकता है।
उन तत्वों की संख्या के आधार पर जो predicate
मेल खाते हैं या, यदि कोई predicate
की आपूर्ति नहीं की गई है, तो स्रोत अनुक्रम में तत्वों की संख्या, वे निम्नानुसार व्यवहार करते हैं:
प्रथम()
- किसी अनुक्रम का पहला तत्व, या प्रदान किए गए
predicate
का पहला तत्व लौटाताpredicate
। - यदि अनुक्रम में कोई तत्व नहीं है, तो एक
InvalidOperationException
संदेश के साथ फेंक दिया जाता है: "अनुक्रम में कोई तत्व नहीं हैं"। - यदि अनुक्रम में प्रदान किए गए
predicate
मेल खाने वाले कोई तत्व नहीं हैं, तो एकInvalidOperationException
संदेश के साथ फेंक दिया जाता है "अनुक्रम में कोई मिलान तत्व नहीं है"।
उदाहरण
// Returns "a":
new[] { "a" }.First();
// Returns "a":
new[] { "a", "b" }.First();
// Returns "b":
new[] { "a", "b" }.First(x => x.Equals("b"));
// Returns "ba":
new[] { "ba", "be" }.First(x => x.Contains("b"));
// Throws InvalidOperationException:
new[] { "ca", "ce" }.First(x => x.Contains("b"));
// Throws InvalidOperationException:
new string[0].First();
FirstOrDefault ()
- किसी अनुक्रम का पहला तत्व, या प्रदान किए गए
predicate
का पहला तत्व लौटाताpredicate
। - यदि अनुक्रम में कोई तत्व नहीं है, या कोई तत्व प्रदान किए गए
predicate
मेल नहीं खाताpredicate
, तोdefault(T)
का उपयोग करके अनुक्रम प्रकार काdefault(T)
मान लौटाता है।
उदाहरण
// Returns "a":
new[] { "a" }.FirstOrDefault();
// Returns "a":
new[] { "a", "b" }.FirstOrDefault();
// Returns "b":
new[] { "a", "b" }.FirstOrDefault(x => x.Equals("b"));
// Returns "ba":
new[] { "ba", "be" }.FirstOrDefault(x => x.Contains("b"));
// Returns null:
new[] { "ca", "ce" }.FirstOrDefault(x => x.Contains("b"));
// Returns null:
new string[0].FirstOrDefault();
अंतिम ()
- किसी अनुक्रम के अंतिम तत्व, या प्रदान किए गए अंतिम तत्व का मिलान करता
predicate
। - यदि अनुक्रम में कोई तत्व नहीं है, तो एक
InvalidOperationException
संदेश के साथ फेंक दिया जाता है "अनुक्रम में कोई तत्व नहीं हैं।" - यदि अनुक्रम में प्रदान किए गए
predicate
मेल खाने वाले कोई तत्व नहीं हैं, तो एकInvalidOperationException
संदेश के साथ फेंक दिया जाता है "अनुक्रम में कोई मिलान तत्व नहीं है"।
उदाहरण
// Returns "a":
new[] { "a" }.Last();
// Returns "b":
new[] { "a", "b" }.Last();
// Returns "a":
new[] { "a", "b" }.Last(x => x.Equals("a"));
// Returns "be":
new[] { "ba", "be" }.Last(x => x.Contains("b"));
// Throws InvalidOperationException:
new[] { "ca", "ce" }.Last(x => x.Contains("b"));
// Throws InvalidOperationException:
new string[0].Last();
LastOrDefault ()
- किसी अनुक्रम के अंतिम तत्व, या प्रदान किए गए अंतिम तत्व का मिलान करता
predicate
। - यदि अनुक्रम में कोई तत्व नहीं है, या कोई तत्व प्रदान किए गए
predicate
मेल नहीं खाताpredicate
, तोdefault(T)
का उपयोग करके अनुक्रम प्रकार काdefault(T)
मान लौटाता है।
उदाहरण
// Returns "a":
new[] { "a" }.LastOrDefault();
// Returns "b":
new[] { "a", "b" }.LastOrDefault();
// Returns "a":
new[] { "a", "b" }.LastOrDefault(x => x.Equals("a"));
// Returns "be":
new[] { "ba", "be" }.LastOrDefault(x => x.Contains("b"));
// Returns null:
new[] { "ca", "ce" }.LastOrDefault(x => x.Contains("b"));
// Returns null:
new string[0].LastOrDefault();
एक()
- यदि अनुक्रम में ठीक एक तत्व होता है, या प्रदान किए गए
predicate
मेल खाने वाला एक तत्व होता है, तो वह तत्व वापस आ जाता है। - यदि अनुक्रम में कोई तत्व नहीं है, या कोई तत्व प्रदान किए गए
predicate
मेल नहीं खाताpredicate
, तो एकInvalidOperationException
संदेश के साथ फेंक दिया जाता है "अनुक्रम में कोई तत्व नहीं हैं"। - यदि अनुक्रम में एक से अधिक तत्व हैं, या प्रदान किए गए
predicate
मेल खाते एक से अधिक तत्व हैं, तो एकInvalidOperationException
संदेश के साथ फेंक दिया जाता है "अनुक्रम में एक से अधिक तत्व होते हैं"। - नोट: मूल्यांकन करने के लिए कि क्या अनुक्रम में एक तत्व शामिल है, अधिकांश दो तत्वों में गणना की जानी है।
उदाहरण
// Returns "a":
new[] { "a" }.Single();
// Throws InvalidOperationException because sequence contains more than one element:
new[] { "a", "b" }.Single();
// Returns "b":
new[] { "a", "b" }.Single(x => x.Equals("b"));
// Throws InvalidOperationException:
new[] { "a", "b" }.Single(x => x.Equals("c"));
// Throws InvalidOperationException:
new string[0].Single();
// Throws InvalidOperationException because sequence contains more than one element:
new[] { "a", "a" }.Single();
SingleOrDefault ()
- यदि अनुक्रम में ठीक एक तत्व होता है, या प्रदान किए गए
predicate
मेल खाने वाला एक तत्व होता है, तो वह तत्व वापस आ जाता है। - यदि अनुक्रम में कोई तत्व नहीं है, या प्रदान किए गए
predicate
मेल खाने वाला कोई तत्व नहींpredicate
, तोdefault(T)
वापस आ जाता है। - यदि अनुक्रम में एक से अधिक तत्व हैं, या प्रदान किए गए
predicate
मेल खाते एक से अधिक तत्व हैं, तो एकInvalidOperationException
संदेश के साथ फेंक दिया जाता है "अनुक्रम में एक से अधिक तत्व होते हैं"। - यदि अनुक्रम में प्रदान किए गए
predicate
मेल खाने वाला कोई तत्व नहींpredicate
, तोdefault(T)
का उपयोग करके अनुक्रम प्रकार काdefault(T)
मान लौटाता है। - नोट: मूल्यांकन करने के लिए कि क्या अनुक्रम में एक तत्व शामिल है, अधिकांश दो तत्वों में गणना की जानी है।
उदाहरण
// Returns "a":
new[] { "a" }.SingleOrDefault();
// returns "a"
new[] { "a", "b" }.SingleOrDefault(x => x == "a");
// Returns null:
new[] { "a", "b" }.SingleOrDefault(x => x == "c");
// Throws InvalidOperationException:
new[] { "a", "a" }.SingleOrDefault(x => x == "a");
// Throws InvalidOperationException:
new[] { "a", "b" }.SingleOrDefault();
// Returns null:
new string[0].SingleOrDefault();
अनुशंसाएँ
यद्यपि आप यह जांचने के लिए कि क्या किसी अनुक्रम में कोई आइटम हैं,
Any
याCount
अधिक विश्वसनीय है, आपFirstOrDefault
,LastOrDefault
याSingleOrDefault
का उपयोग कर सकते हैं। ऐसा इसलिए है क्योंकि इन तीन विधियों में से एक सेdefault(T)
का वापसी मान यह साबित नहीं करता है कि अनुक्रम खाली है, क्योंकि अनुक्रम के पहले / अंतिम / एकल तत्व का मान समान रूप सेdefault(T)
हो सकताdefault(T)
तय करें कि कौन सी विधियाँ आपके कोड के उद्देश्य को सबसे अधिक उपयुक्त बनाती हैं। उदाहरण के लिए,
Single
उपयोग केवल तभी करें जब आपको यह सुनिश्चित करना चाहिए कि आपके विधेय से मेल खाते वाले संग्रह में एक ही आइटम है - अन्यथाFirst
उपयोग करें; के रूप मेंSingle
एक अपवाद फेंक अगर अनुक्रम एक से अधिक मिलान तत्व है। यह पाठ्यक्रम "* OrDefault" -counterparts पर भी लागू होता है।दक्षता के बारे में: हालाँकि यह सुनिश्चित करना उचित है कि केवल एक आइटम (
Single
) है या, या तो केवल एक या शून्य (SingleOrDefault
) आइटम, किसी क्वेरी के द्वारा लौटाए जाते हैं, इन दोनों विधियों के लिए अधिक आवश्यकता होती है, और अक्सर संपूर्णता, संग्रह की क्वेरी के लिए किसी दूसरे मैच में वहां सुनिश्चित करने के लिए जांच की जाएगी। यह, उदाहरण के लिए,First
विधि के व्यवहार के विपरीत है, जिसे पहला मैच खोजने के बाद संतुष्ट किया जा सकता है।
के सिवाय
अपवर्जन विधि उन वस्तुओं के सेट को लौटाती है जो पहले संग्रह में निहित हैं लेकिन दूसरे में समाहित नहीं हैं। डिफ़ॉल्ट IEqualityComparer
का उपयोग दो सेटों के भीतर वस्तुओं की तुलना करने के लिए किया जाता है। एक अधिभार है जो एक IEqualityComparer
को एक तर्क के रूप में स्वीकार करता है।
उदाहरण:
int[] first = { 1, 2, 3, 4 };
int[] second = { 0, 2, 3, 5 };
IEnumerable<int> inFirstButNotInSecond = first.Except(second);
// inFirstButNotInSecond = { 1, 4 }
आउटपुट:
1
4
इस स्थिति में .Except(second)
सरणी में शामिल तत्वों को .Except(second)
second
, अर्थात् 2 और 3 (0 और 5 first
सरणी में निहित नहीं हैं और छोड़ दिए गए हैं)।
ध्यान दें कि Except
कि Distinct
(यानी, यह दोहराया तत्वों को हटा देता है)। उदाहरण के लिए:
int[] third = { 1, 1, 1, 2, 3, 4 };
IEnumerable<int> inThirdButNotInSecond = third.Except(second);
// inThirdButNotInSecond = { 1, 4 }
आउटपुट:
1
4
इस स्थिति में, तत्व 1 और 4 केवल एक बार वापस आ जाते हैं।
IEquatable
लागू IEquatable
या फ़ंक्शन प्रदान करना IEqualityComparer
तत्वों की तुलना करने के लिए एक अलग विधि का उपयोग करने की अनुमति देगा। ध्यान दें कि GetHashCode
पद्धति को भी ओवरराइड किया जाना चाहिए ताकि यह object
के लिए एक समान हैश कोड IEquatable
जो IEquatable
कार्यान्वयन के अनुसार समान है।
IEquitable के साथ उदाहरण:
class Holiday : IEquatable<Holiday>
{
public string Name { get; set; }
public bool Equals(Holiday other)
{
return Name == other.Name;
}
// GetHashCode must return true whenever Equals returns true.
public override int GetHashCode()
{
//Get hash code for the Name field if it is not null.
return Name?.GetHashCode() ?? 0;
}
}
public class Program
{
public static void Main()
{
List<Holiday> holidayDifference = new List<Holiday>();
List<Holiday> remoteHolidays = new List<Holiday>
{
new Holiday { Name = "Xmas" },
new Holiday { Name = "Hanukkah" },
new Holiday { Name = "Ramadan" }
};
List<Holiday> localHolidays = new List<Holiday>
{
new Holiday { Name = "Xmas" },
new Holiday { Name = "Ramadan" }
};
holidayDifference = remoteHolidays
.Except(localHolidays)
.ToList();
holidayDifference.ForEach(x => Console.WriteLine(x.Name));
}
}
आउटपुट:
हनुका
SelectMany: दृश्यों का एक क्रम समतल
var sequenceOfSequences = new [] { new [] { 1, 2, 3 }, new [] { 4, 5 }, new [] { 6 } };
var sequence = sequenceOfSequences.SelectMany(x => x);
// returns { 1, 2, 3, 4, 5, 6 }
यदि आपके पास SelectMany()
उपयोग करें, या आप अनुक्रमों का अनुक्रम बना रहे हैं, लेकिन आप एक लंबे अनुक्रम के रूप में परिणाम चाहते हैं।
LINQ क्वेरी सिंटैक्स में:
var sequence = from subSequence in sequenceOfSequences
from item in subSequence
select item;
यदि आपके पास संग्रह का संग्रह है और एक ही समय में माता-पिता और बच्चे के संग्रह से डेटा पर काम करने में सक्षम होना चाहते हैं, तो यह SelectMany
साथ भी संभव है।
चलो सरल वर्गों को परिभाषित करते हैं
public class BlogPost
{
public int Id { get; set; }
public string Content { get; set; }
public List<Comment> Comments { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string Content { get; set; }
}
मान लेते हैं कि हमारे पास निम्नलिखित संग्रह है।
List<BlogPost> posts = new List<BlogPost>()
{
new BlogPost()
{
Id = 1,
Comments = new List<Comment>()
{
new Comment()
{
Id = 1,
Content = "It's really great!",
},
new Comment()
{
Id = 2,
Content = "Cool post!"
}
}
},
new BlogPost()
{
Id = 2,
Comments = new List<Comment>()
{
new Comment()
{
Id = 3,
Content = "I don't think you're right",
},
new Comment()
{
Id = 4,
Content = "This post is a complete nonsense"
}
}
}
};
अब हम टिप्पणियों का चयन करना चाहते Content
के साथ Id
की BlogPost
इस टिप्पणी के साथ जुड़े। ऐसा करने के लिए, हम उचित SelectMany
अधिभार का उपयोग कर सकते हैं।
var commentsWithIds = posts.SelectMany(p => p.Comments, (post, comment) => new { PostId = post.Id, CommentContent = comment.Content });
हमारी commentsWithIds
इस तरह दिखती हैं
{
PostId = 1,
CommentContent = "It's really great!"
},
{
PostId = 1,
CommentContent = "Cool post!"
},
{
PostId = 2,
CommentContent = "I don't think you're right"
},
{
PostId = 2,
CommentContent = "This post is a complete nonsense"
}
SelectMany
SelectMany LINQ विधि 'सपाट' एक IEnumerable<IEnumerable<T>>
एक में IEnumerable<T>
। भीतर टी तत्वों के सभी IEnumerable
स्रोत में शामिल उदाहरणों IEnumerable
एक एकल में संयुक्त हो जाएगा IEnumerable
।
var words = new [] { "a,b,c", "d,e", "f" };
var splitAndCombine = words.SelectMany(x => x.Split(','));
// returns { "a", "b", "c", "d", "e", "f" }
यदि आप एक चयनकर्ता फ़ंक्शन का उपयोग करते हैं जो इनपुट तत्वों को अनुक्रमों में बदल देता है, तो परिणाम उन अनुक्रमों के तत्व एक-एक करके वापस आ जाएंगे।
ध्यान दें कि, Select()
विपरीत, आउटपुट में तत्वों की संख्या उसी तरह की होने की आवश्यकता नहीं है जैसी इनपुट में थी।
अधिक वास्तविक दुनिया उदाहरण
class School
{
public Student[] Students { get; set; }
}
class Student
{
public string Name { get; set; }
}
var schools = new [] {
new School(){ Students = new [] { new Student { Name="Bob"}, new Student { Name="Jack"} }},
new School(){ Students = new [] { new Student { Name="Jim"}, new Student { Name="John"} }}
};
var allStudents = schools.SelectMany(s=> s.Students);
foreach(var student in allStudents)
{
Console.WriteLine(student.Name);
}
आउटपुट:
बॉब
जैक
जिम
जॉन
सब
All
का उपयोग चेक करने के लिए किया जाता है, अगर संग्रह के सभी तत्व एक शर्त से मेल खाते हैं या नहीं।
यह भी देखें: .Any
1. खाली पैरामीटर
सभी : खाली पैरामीटर के साथ उपयोग करने की अनुमति नहीं है।
2. लैम्बडा अभिव्यक्ति पैरामीटर के रूप में
सभी : यदि संग्रह के सभी तत्व लंबोदर अभिव्यक्ति को संतुष्ट करते हैं और अन्यथा false
तो यह true
:
var numbers = new List<int>(){ 1, 2, 3, 4, 5};
bool result = numbers.All(i => i < 10); // true
bool result = numbers.All(i => i >= 3); // false
3. खाली संग्रह
सभी : अगर संग्रह खाली है और एक लैम्ब्डा अभिव्यक्ति की आपूर्ति की जाती true
तो यह true
है:
var numbers = new List<int>();
bool result = numbers.All(i => i >= 0); // true
नोट: जैसे ही किसी तत्व को स्थिति से मेल नहीं खाता, All
संग्रह के पुनरावृत्ति को रोक देंगे। इसका मतलब यह है कि संग्रह जरूरी पूरी तरह से एनुमरेटेड नहीं होगा; यह केवल काफी दूर तक पाया जाएगा कि पहली वस्तु हालत से मेल नहीं खा रही है।
टाइप करने के लिए टाइप / कास्ट तत्वों द्वारा क्वेरी संग्रह
interface IFoo { }
class Foo : IFoo { }
class Bar : IFoo { }
var item0 = new Foo();
var item1 = new Foo();
var item2 = new Bar();
var item3 = new Bar();
var collection = new IFoo[] { item0, item1, item2, item3 };
OfType
का उपयोग करना
var foos = collection.OfType<Foo>(); // result: IEnumerable<Foo> with item0 and item1
var bars = collection.OfType<Bar>(); // result: IEnumerable<Bar> item item2 and item3
var foosAndBars = collection.OfType<IFoo>(); // result: IEnumerable<IFoo> with all four items
Where
का उपयोग करना
var foos = collection.Where(item => item is Foo); // result: IEnumerable<IFoo> with item0 and item1
var bars = collection.Where(item => item is Bar); // result: IEnumerable<IFoo> with item2 and item3
Cast
का उपयोग करना
var bars = collection.Cast<Bar>(); // throws InvalidCastException on the 1st item
var foos = collection.Cast<Foo>(); // throws InvalidCastException on the 3rd item
var foosAndBars = collection.Cast<IFoo>(); // OK
संघ
डिफ़ॉल्ट समानता तुलनित्र का उपयोग करके एक अलग संग्रह बनाने के लिए दो संग्रह जोड़ता है
int[] numbers1 = { 1, 2, 3 };
int[] numbers2 = { 2, 3, 4, 5 };
var allElement = numbers1.Union(numbers2); // AllElement now contains 1,2,3,4,5
कार्यभार संभाला
एक सामान्य कुंजी के माध्यम से डेटा को अलग-अलग सूचियों या तालिकाओं को जोड़ने के लिए जोड़ों का उपयोग किया जाता है।
SQL की तरह, LINQ में निम्न प्रकार के जॉइन समर्थित हैं:
इनर, लेफ्ट, राइट, क्रॉस और फुल आउटर जॉइन करता है।
नीचे दिए गए उदाहरणों में निम्नलिखित दो सूचियों का उपयोग किया गया है:
var first = new List<string>(){ "a","b","c"}; // Left data
var second = new List<string>(){ "a", "c", "d"}; // Right data
(आंतरिक रूप से जुड़ा
var result = from f in first
join s in second on f equals s
select new { f, s };
var result = first.Join(second,
f => f,
s => s,
(f, s) => new { f, s });
// Result: {"a","a"}
// {"c","c"}
बाईं ओर का बाहरी जोड़
var leftOuterJoin = from f in first
join s in second on f equals s into temp
from t in temp.DefaultIfEmpty()
select new { First = f, Second = t};
// Or can also do:
var leftOuterJoin = from f in first
from s in second.Where(x => x == f).DefaultIfEmpty()
select new { First = f, Second = s};
// Result: {"a","a"}
// {"b", null}
// {"c","c"}
// Left outer join method syntax
var leftOuterJoinFluentSyntax = first.GroupJoin(second,
f => f,
s => s,
(f, s) => new { First = f, Second = s })
.SelectMany(temp => temp.Second.DefaultIfEmpty(),
(f, s) => new { First = f.First, Second = s });
राइट आउटर जॉइन करें
var rightOuterJoin = from s in second
join f in first on s equals f into temp
from t in temp.DefaultIfEmpty()
select new {First=t,Second=s};
// Result: {"a","a"}
// {"c","c"}
// {null,"d"}
क्रॉस जॉइन करें
var CrossJoin = from f in first
from s in second
select new { f, s };
// Result: {"a","a"}
// {"a","c"}
// {"a","d"}
// {"b","a"}
// {"b","c"}
// {"b","d"}
// {"c","a"}
// {"c","c"}
// {"c","d"}
पूर्ण बाहरी सम्मिलित हों
var fullOuterjoin = leftOuterJoin.Union(rightOuterJoin);
// Result: {"a","a"}
// {"b", null}
// {"c","c"}
// {null,"d"}
व्यावहारिक उदाहरण
ऊपर दिए गए उदाहरणों में एक सरल डेटा संरचना है, ताकि आप तकनीकी रूप से अलग-अलग LINQ जॉइन को समझने पर ध्यान केंद्रित कर सकें, लेकिन वास्तविक दुनिया में आपको उन कॉलमों से तालमेल रखना होगा जिनमें आपको शामिल होने की आवश्यकता है।
निम्नलिखित उदाहरण में, केवल एक वर्ग Region
उपयोग किया गया है, वास्तव में आप दो या दो से अधिक विभिन्न तालिकाओं में शामिल होंगे जो समान कुंजी रखते हैं (इस उदाहरण में first
और second
सामान्य कुंजी ID
माध्यम से शामिल होते हैं)।
उदाहरण: निम्नलिखित डेटा संरचना पर विचार करें:
public class Region
{
public Int32 ID;
public string RegionDescription;
public Region(Int32 pRegionID, string pRegionDescription=null)
{
ID = pRegionID; RegionDescription = pRegionDescription;
}
}
अब डेटा तैयार करें (यानी डेटा से आबाद):
// Left data
var first = new List<Region>()
{ new Region(1), new Region(3), new Region(4) };
// Right data
var second = new List<Region>()
{
new Region(1, "Eastern"), new Region(2, "Western"),
new Region(3, "Northern"), new Region(4, "Southern")
};
आप देख सकते हैं कि इस उदाहरण में first
किसी भी क्षेत्र का विवरण नहीं है, इसलिए आप उन्हें second
से second
। तब भीतरी जुड़ाव ऐसा दिखेगा:
// do the inner join
var result = from f in first
join s in second on f.ID equals s.ID
select new { f.ID, s.RegionDescription };
// Result: {1,"Eastern"}
// {3, Northern}
// {4,"Southern"}
इस परिणाम ने मक्खी पर अनाम वस्तुओं का निर्माण किया है, जो ठीक है, लेकिन हमने पहले से ही एक उचित वर्ग बनाया है - इसलिए हम इसे निर्दिष्ट कर सकते हैं: select new { f.ID, s.RegionDescription };
बजाय select new { f.ID, s.RegionDescription };
हम कह सकते हैं कि select new Region(f.ID, s.RegionDescription);
, जो समान डेटा लौटाएगा लेकिन प्रकार Region
की वस्तुओं को बनाएगा - जो अन्य वस्तुओं के साथ संगतता बनाए रखेगा।
अलग
एक IEnumerable
से अद्वितीय मान लौटाता है। डिफ़ॉल्ट समानता समानता का उपयोग करके विशिष्टता निर्धारित की जाती है।
int[] array = { 1, 2, 3, 4, 2, 5, 3, 1, 2 };
var distinct = array.Distinct();
// distinct = { 1, 2, 3, 4, 5 }
एक कस्टम डेटा प्रकार की तुलना करने के लिए, हम लागू करने की आवश्यकता IEquatable<T>
इंटरफेस और प्रदान GetHashCode
और Equals
प्रकार के लिए तरीके। या समानता की तुलना करने वाले को ओवरराइड किया जा सकता है:
class SSNEqualityComparer : IEqualityComparer<Person> {
public bool Equals(Person a, Person b) => return a.SSN == b.SSN;
public int GetHashCode(Person p) => p.SSN;
}
List<Person> people;
distinct = people.Distinct(SSNEqualityComparer);
GroupBy एक या कई फ़ील्ड
मान लेते हैं कि हमारे पास कुछ फिल्मी मॉडल हैं:
public class Film {
public string Title { get; set; }
public string Category { get; set; }
public int Year { get; set; }
}
श्रेणी संपत्ति द्वारा समूह:
foreach (var grp in films.GroupBy(f => f.Category)) {
var groupCategory = grp.Key;
var numberOfFilmsInCategory = grp.Count();
}
श्रेणी और वर्ष के अनुसार समूह:
foreach (var grp in films.GroupBy(f => new { Category = f.Category, Year = f.Year })) {
var groupCategory = grp.Key.Category;
var groupYear = grp.Key.Year;
var numberOfFilmsInCategory = grp.Count();
}
विभिन्न लाइनक विधियों के साथ रेंज का उपयोग करना
आप Linq एक लाइनर में छोरों के लिए परिवर्तित करने के लिए Linq प्रश्नों के साथ Enumerable वर्ग का उपयोग कर सकते हैं।
उदाहरण का चयन करें
ऐसा करने का विरोध:
var asciiCharacters = new List<char>();
for (var x = 0; x < 256; x++)
{
asciiCharacters.Add((char)x);
}
तुम यह केर सकते हो:
var asciiCharacters = Enumerable.Range(0, 256).Select(a => (char) a);
कहां का उदाहरण
इस उदाहरण में, 100 नंबर उत्पन्न होंगे और यहां तक कि निकाले जाएंगे
var evenNumbers = Enumerable.Range(1, 100).Where(a => a % 2 == 0);
क्वेरी ऑर्डरिंग - ऑर्डरबाय () तबबाय () ऑर्डरबायस्केंडिंग () फिरबायस्केंडिंग ()
string[] names= { "mark", "steve", "adam" };
आरोही:
क्वेरी सिंटैक्स
var sortedNames =
from name in names
orderby name
select name;
विधि सिंटेक्स
var sortedNames = names.OrderBy(name => name);
क्रमबद्ध नामों में निम्नलिखित क्रम में नाम शामिल हैं: "एडाम", "मार्क", "स्टिव"
अवरोही:
क्वेरी सिंटैक्स
var sortedNames =
from name in names
orderby name descending
select name;
विधि सिंटेक्स
var sortedNames = names.OrderByDescending(name => name);
क्रमबद्ध नामों में निम्नलिखित क्रम में नाम शामिल हैं: "स्टीव", "निशान", "एडम"
कई क्षेत्रों द्वारा आदेश
Person[] people =
{
new Person { FirstName = "Steve", LastName = "Collins", Age = 30},
new Person { FirstName = "Phil" , LastName = "Collins", Age = 28},
new Person { FirstName = "Adam" , LastName = "Ackerman", Age = 29},
new Person { FirstName = "Adam" , LastName = "Ackerman", Age = 15}
};
क्वेरी सिंटैक्स
var sortedPeople = from person in people
orderby person.LastName, person.FirstName, person.Age descending
select person;
विधि सिंटेक्स
sortedPeople = people.OrderBy(person => person.LastName)
.ThenBy(person => person.FirstName)
.ThenByDescending(person => person.Age);
परिणाम
1. Adam Ackerman 29
2. Adam Ackerman 15
3. Phil Collins 28
4. Steve Collins 30
मूल बातें
LINQ संग्रह (या सरणियों) को क्वेरी करने के लिए काफी फायदेमंद है।
उदाहरण के लिए, निम्न नमूना डेटा दिया गया है:
var classroom = new Classroom
{
new Student { Name = "Alice", Grade = 97, HasSnack = true },
new Student { Name = "Bob", Grade = 82, HasSnack = false },
new Student { Name = "Jimmy", Grade = 71, HasSnack = true },
new Student { Name = "Greg", Grade = 90, HasSnack = false },
new Student { Name = "Joe", Grade = 59, HasSnack = false }
}
हम LINQ सिंटैक्स का उपयोग करके इस डेटा पर "क्वेरी" कर सकते हैं। उदाहरण के लिए, उन सभी छात्रों को पुनः प्राप्त करने के लिए जिनके पास आज अल्पाहार है:
var studentsWithSnacks = from s in classroom.Students
where s.HasSnack
select s;
या, 90 या उससे ऊपर की कक्षा वाले छात्रों को पुनः प्राप्त करने के लिए, और केवल उनके नाम वापस करें, न कि पूर्ण Student
वस्तु:
var topStudentNames = from s in classroom.Students
where s.Grade >= 90
select s.Name;
LINQ फीचर में दो सिंटेक्स शामिल हैं जो समान कार्य करते हैं, लगभग समान प्रदर्शन करते हैं, लेकिन बहुत अलग तरीके से लिखे जाते हैं। ऊपर दिए गए उदाहरण में वाक्यविन्यास को क्वेरी वाक्यविन्यास कहा जाता है। हालाँकि, निम्न उदाहरण विधि सिंटैक्स दिखाता है। जैसा उदाहरण ऊपर दिया गया है वैसा ही डेटा लौटाया जाएगा, लेकिन क्वेरी लिखने का तरीका अलग है।
var topStudentNames = classroom.Students
.Where(s => s.Grade >= 90)
.Select(s => s.Name);
समूह द्वारा
GroupBy विभिन्न समूहों में IEnumerable<T>
वस्तुओं के संग्रह को सॉर्ट करने का एक आसान तरीका है।
सरल उदाहरण
इस पहले उदाहरण में, हम दो समूहों के साथ समाप्त होते हैं, विषम और यहां तक कि आइटम भी।
List<int> iList = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var grouped = iList.GroupBy(x => x % 2 == 0);
//Groups iList into odd [13579] and even[2468] items
foreach(var group in grouped)
{
foreach (int item in group)
{
Console.Write(item); // 135792468 (first odd then even)
}
}
अधिक जटिल उदाहरण
आइए एक उदाहरण के रूप में उम्र के आधार पर लोगों की एक सूची बनाएं। सबसे पहले, हम एक व्यक्ति वस्तु बनाएँगे जिसमें दो गुण हैं, नाम और आयु।
public class Person
{
public int Age {get; set;}
public string Name {get; set;}
}
फिर हम विभिन्न नामों और उम्र वाले लोगों की अपनी नमूना सूची बनाते हैं।
List<Person> people = new List<Person>();
people.Add(new Person{Age = 20, Name = "Mouse"});
people.Add(new Person{Age = 30, Name = "Neo"});
people.Add(new Person{Age = 40, Name = "Morpheus"});
people.Add(new Person{Age = 30, Name = "Trinity"});
people.Add(new Person{Age = 40, Name = "Dozer"});
people.Add(new Person{Age = 40, Name = "Smith"});
फिर हम उम्र के हिसाब से लोगों की सूची बनाने के लिए एक LINQ क्वेरी बनाते हैं।
var query = people.GroupBy(x => x.Age);
ऐसा करने पर, हम प्रत्येक समूह के लिए आयु देख सकते हैं, और समूह में प्रत्येक व्यक्ति की एक सूची हो सकती है।
foreach(var result in query)
{
Console.WriteLine(result.Key);
foreach(var person in result)
Console.WriteLine(person.Name);
}
इसका परिणाम निम्न आउटपुट में होता है:
20
Mouse
30
Neo
Trinity
40
Morpheus
Dozer
Smith
आप .NET फिडल पर लाइव डेमो के साथ खेल सकते हैं
कोई भी
यह जांचने के लिए Any
का उपयोग किया जाता है कि संग्रह का कोई तत्व किसी स्थिति से मेल खाता है या नहीं।
यह भी देखें:। सभी , किसी भी और FirstOrDefault: सबसे अच्छा अभ्यास
1. खाली पैरामीटर
कोई : यदि संग्रह खाली है तो संग्रह में कोई तत्व और false
होने पर रिटर्न true
है:
var numbers = new List<int>();
bool result = numbers.Any(); // false
var numbers = new List<int>(){ 1, 2, 3, 4, 5};
bool result = numbers.Any(); //true
2. लैम्बडा अभिव्यक्ति पैरामीटर के रूप में
कोई भी : यदि संग्रह में एक या अधिक तत्व हैं जो लंबोदर अभिव्यक्ति में स्थिति को पूरा करते हैं, तो यह true
:
var arrayOfStrings = new string[] { "a", "b", "c" };
arrayOfStrings.Any(item => item == "a"); // true
arrayOfStrings.Any(item => item == "d"); // false
3. खाली संग्रह
कोई भी : यदि संग्रह खाली है और एक लैम्ब्डा एक्सप्रेशन दिया गया है तो false
रिटर्न:
var numbers = new List<int>();
bool result = numbers.Any(i => i >= 0); // false
नोट: जैसे ही यह स्थिति से मेल खाता तत्व पाता है, Any
संग्रह के पुनरावृत्ति को रोक देगा। इसका मतलब यह है कि संग्रह जरूरी पूरी तरह से एनुमरेटेड नहीं होगा; हालत से मेल खाने वाले पहले आइटम को खोजने के लिए यह केवल काफी दूर होगा।
ToDictionary
एक ToDictionary()
दिए गए IEnumerable<T>
स्रोत के आधार पर एक Dictionary<TKey, TElement>
संग्रह जनरेट करने के लिए ToDictionary()
LINQ विधि का उपयोग किया जा सकता है।
IEnumerable<User> users = GetUsers();
Dictionary<int, User> usersById = users.ToDictionary(x => x.Id);
इस उदाहरण में, ToDictionary
लिए दिया गया एकल तर्क ToDictionary
Func<TSource, TKey>
, जो प्रत्येक तत्व की कुंजी देता है।
यह निम्नलिखित ऑपरेशन करने का एक संक्षिप्त तरीका है:
Dictionary<int, User> usersById = new Dictionary<int User>();
foreach (User u in users)
{
usersById.Add(u.Id, u);
}
आप ToDictionary
विधि के लिए एक दूसरा पैरामीटर भी पास कर सकते हैं, जो कि Func<TSource, TElement>
और प्रत्येक प्रविष्टि के लिए जोड़ा जाने वाला Value
लौटाता है।
IEnumerable<User> users = GetUsers();
Dictionary<int, string> userNamesById = users.ToDictionary(x => x.Id, x => x.Name);
मुख्य मूल्यों की तुलना करने के लिए उपयोग किए जाने वाले IComparer
को निर्दिष्ट करना भी संभव है। यह तब उपयोगी हो सकता है जब कुंजी एक स्ट्रिंग है और आप चाहते हैं कि यह केस-असंवेदनशील से मेल खाए।
IEnumerable<User> users = GetUsers();
Dictionary<string, User> usersByCaseInsenstiveName = users.ToDictionary(x => x.Name, StringComparer.InvariantCultureIgnoreCase);
var user1 = usersByCaseInsenstiveName["john"];
var user2 = usersByCaseInsenstiveName["JOHN"];
user1 == user2; // Returns true
नोट: ToDictionary
विधि के लिए सभी कुंजियों का विशिष्ट होना आवश्यक है, कोई डुप्लिकेट कुंजियाँ नहीं होनी चाहिए। यदि वहाँ हैं, तो एक अपवाद फेंक दिया गया है: ArgumentException: An item with the same key has already been added.
अपवाद ArgumentException: An item with the same key has already been added.
यदि आपके पास एक ऐसा परिदृश्य है जहाँ आप जानते हैं कि आपके पास एक ही कुंजी के साथ कई तत्व होंगे, तो आप इसके बजाय ToLookup
का उपयोग करना बेहतर ToLookup
हैं।
कुल
Aggregate
एक अनुक्रम पर एक संचायक कार्य को लागू करता है।
int[] intList = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = intList.Aggregate((prevSum, current) => prevSum + current);
// sum = 55
- पहले चरण पर
prevSum = 1
- दूसरे
prevSum = prevSum(at the first step) + 2
- I-th स्टेप
prevSum = prevSum(at the (i-1) step) + i-th element of the array
string[] stringList = { "Hello", "World", "!" };
string joinedString = stringList.Aggregate((prev, current) => prev + " " + current);
// joinedString = "Hello World !"
Aggregate
का दूसरा ओवरलोड भी एक seed
पैरामीटर प्राप्त करता है जो प्रारंभिक संचयकर्ता मूल्य है। यह एक से अधिक बार पुनरावृति किए बिना संग्रह पर कई स्थितियों की गणना करने के लिए उपयोग किया जा सकता है।
List<int> items = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
items
के संग्रह के लिए हम गणना करना चाहते हैं
- कुल
.Count
- सम संख्याएँ
- प्रत्येक आइटम को इकट्ठा करें
Aggregate
का उपयोग करके इसे इस तरह किया जा सकता है:
var result = items.Aggregate(new { Total = 0, Even = 0, FourthItems = new List<int>() },
(accumelative,item) =>
new {
Total = accumelative.Total + 1,
Even = accumelative.Even + (item % 2 == 0 ? 1 : 0),
FourthItems = (accumelative.Total + 1)%4 == 0 ?
new List<int>(accumelative.FourthItems) { item } :
accumelative.FourthItems
});
// Result:
// Total = 12
// Even = 6
// FourthItems = [4, 8, 12]
ध्यान दें कि बीज के रूप में एक अनाम प्रकार का उपयोग करके प्रत्येक वस्तु को एक नई वस्तु को तुरंत देना होगा क्योंकि गुण केवल पढ़े जाते हैं। एक कस्टम वर्ग का उपयोग करके केवल जानकारी को असाइन किया जा सकता है और किसी new
की जरूरत नहीं है (केवल प्रारंभिक seed
पैरामीटर देते समय
Linq क्वेरी के अंदर एक वैरिएबल को परिभाषित करना (कीवर्ड दें)
एक linq अभिव्यक्ति के अंदर एक चर को परिभाषित करने के लिए, आप लेट कीवर्ड का उपयोग कर सकते हैं। यह आमतौर पर मध्यवर्ती उप-प्रश्नों के परिणामों को संग्रहीत करने के लिए किया जाता है, उदाहरण के लिए:
int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var aboveAverages = from number in numbers
let average = numbers.Average()
let nSquared = Math.Pow(number,2)
where nSquared > average
select number;
Console.WriteLine("The average of the numbers is {0}.", numbers.Average());
foreach (int n in aboveAverages)
{
Console.WriteLine("Query result includes number {0} with square of {1}.", n, Math.Pow(n,2));
}
आउटपुट:
संख्याओं का औसत 4.5 है।
क्वेरी परिणाम में 9 के वर्ग के साथ नंबर 3 शामिल है।
क्वेरी परिणाम में 16 के वर्ग के साथ नंबर 4 शामिल है।
क्वेरी परिणाम में 25 के वर्ग के साथ नंबर 5 शामिल है।
क्वेरी परिणाम में 36 के वर्ग के साथ संख्या 6 शामिल है।
क्वेरी परिणाम में 49 के वर्ग के साथ संख्या 7 शामिल है।
क्वेरी परिणाम में 64 के वर्ग के साथ नंबर 8 शामिल है।
क्वेरी परिणाम में 81 के वर्ग के साथ संख्या 9 शामिल है।
SkipWhile
SkipWhile()
का उपयोग पहले गैर-मिलान तक तत्वों को बाहर करने के लिए किया जाता है (यह अधिकांश के लिए सहज हो सकता है)
int[] list = { 42, 42, 6, 6, 6, 42 };
var result = list.SkipWhile(i => i == 42);
// Result: 6, 6, 6, 42
DefaultIfEmpty
DefaultIfEmpty का उपयोग डिफ़ॉल्ट तत्व को वापस करने के लिए किया जाता है यदि अनुक्रम में कोई तत्व नहीं है। यह तत्व प्रकार का डिफ़ॉल्ट हो सकता है या उपयोगकर्ता उस प्रकार का परिभाषित उदाहरण हो सकता है। उदाहरण:
var chars = new List<string>() { "a", "b", "c", "d" };
chars.DefaultIfEmpty("N/A").FirstOrDefault(); // returns "a";
chars.Where(str => str.Length > 1)
.DefaultIfEmpty("N/A").FirstOrDefault(); // return "N/A"
chars.Where(str => str.Length > 1)
.DefaultIfEmpty().First(); // returns null;
बाएं जोड़ों में उपयोग :
DefaultIfEmpty
के साथ पारंपरिक Linq Join डिफ़ॉल्ट वस्तु वापस कर सकता है यदि कोई मैच नहीं मिला। इस प्रकार एसक्यूएल के लेफ्ट जॉइन के रूप में कार्य करना। उदाहरण:
var leftSequence = new List<int>() { 99, 100, 5, 20, 102, 105 };
var rightSequence = new List<char>() { 'a', 'b', 'c', 'i', 'd' };
var numbersAsChars = from l in leftSequence
join r in rightSequence
on l equals (int)r into leftJoin
from result in leftJoin.DefaultIfEmpty('?')
select new
{
Number = l,
Character = result
};
foreach(var item in numbersAsChars)
{
Console.WriteLine("Num = {0} ** Char = {1}", item.Number, item.Character);
}
ouput:
Num = 99 Char = c
Num = 100 Char = d
Num = 5 Char = ?
Num = 20 Char = ?
Num = 102 Char = ?
Num = 105 Char = i
उस स्थिति में जहां एक DefaultIfEmpty
का उपयोग किया जाता है (डिफ़ॉल्ट मान निर्दिष्ट किए बिना) और इसके परिणामस्वरूप सही अनुक्रम पर कोई मिलान आइटम नहीं होगा, किसी को यह सुनिश्चित करना होगा कि ऑब्जेक्ट उसके गुणों तक पहुंचने से पहले null
नहीं है। अन्यथा इसका परिणाम NullReferenceException
में होगा। उदाहरण:
var leftSequence = new List<int> { 1, 2, 5 };
var rightSequence = new List<dynamic>()
{
new { Value = 1 },
new { Value = 2 },
new { Value = 3 },
new { Value = 4 },
};
var numbersAsChars = (from l in leftSequence
join r in rightSequence
on l equals r.Value into leftJoin
from result in leftJoin.DefaultIfEmpty()
select new
{
Left = l,
// 5 will not have a matching object in the right so result
// will be equal to null.
// To avoid an error use:
// - C# 6.0 or above - ?.
// - Under - result == null ? 0 : result.Value
Right = result?.Value
}).ToList();
SequenceEqual
SequenceEqual
का उपयोग दो IEnumerable<T>
दृश्यों को एक दूसरे के साथ तुलना करने के लिए किया जाता है।
int[] a = new int[] {1, 2, 3};
int[] b = new int[] {1, 2, 3};
int[] c = new int[] {1, 3, 2};
bool returnsTrue = a.SequenceEqual(b);
bool returnsFalse = a.SequenceEqual(c);
गिनती और लॉन्गकाउंट
IEnumerable<T>
में तत्वों की संख्या की Count
। Count
एक वैकल्पिक विधेय पैरामीटर को भी उजागर करता है जो आपको उन तत्वों को फ़िल्टर करने की अनुमति देता है जिन्हें आप गिनना चाहते हैं।
int[] array = { 1, 2, 3, 4, 2, 5, 3, 1, 2 };
int n = array.Count(); // returns the number of elements in the array
int x = array.Count(i => i > 2); // returns the number of elements in the array greater than 2
LongCount
Count
तरह ही काम करता है लेकिन वापसी का प्रकार long
और इसका उपयोग IEnumerable<T>
अनुक्रमों की गिनती के लिए किया जाता है जो कि int.MaxValue
से अधिक लंबे होते हैं int.MaxValue
int[] array = GetLargeArray();
long n = array.LongCount(); // returns the number of elements in the array
long x = array.LongCount(i => i > 100); // returns the number of elements in the array greater than 100
आकस्मिक रूप से एक क्वेरी का निर्माण
क्योंकि LINQ आस्थगित निष्पादन का उपयोग करता है, हमारे पास एक क्वेरी ऑब्जेक्ट हो सकता है जिसमें वास्तव में मान शामिल नहीं हैं, लेकिन मूल्यांकन किए जाने पर मान वापस कर देंगे। इस प्रकार हम गतिशील रूप से हमारे नियंत्रण प्रवाह के आधार पर क्वेरी का निर्माण कर सकते हैं, और समाप्त होने के बाद इसका मूल्यांकन कर सकते हैं:
IEnumerable<VehicleModel> BuildQuery(int vehicleType, SearchModel search, int start = 1, int count = -1) {
IEnumerable<VehicleModel> query = _entities.Vehicles
.Where(x => x.Active && x.Type == vehicleType)
.Select(x => new VehicleModel {
Id = v.Id,
Year = v.Year,
Class = v.Class,
Make = v.Make,
Model = v.Model,
Cylinders = v.Cylinders ?? 0
});
हम सशर्त रूप से फ़िल्टर लागू कर सकते हैं:
if (!search.Years.Contains("all", StringComparer.OrdinalIgnoreCase))
query = query.Where(v => search.Years.Contains(v.Year));
if (!search.Makes.Contains("all", StringComparer.OrdinalIgnoreCase)) {
query = query.Where(v => search.Makes.Contains(v.Make));
}
if (!search.Models.Contains("all", StringComparer.OrdinalIgnoreCase)) {
query = query.Where(v => search.Models.Contains(v.Model));
}
if (!search.Cylinders.Equals("all", StringComparer.OrdinalIgnoreCase)) {
decimal minCylinders = 0;
decimal maxCylinders = 0;
switch (search.Cylinders) {
case "2-4":
maxCylinders = 4;
break;
case "5-6":
minCylinders = 5;
maxCylinders = 6;
break;
case "8":
minCylinders = 8;
maxCylinders = 8;
break;
case "10+":
minCylinders = 10;
break;
}
if (minCylinders > 0) {
query = query.Where(v => v.Cylinders >= minCylinders);
}
if (maxCylinders > 0) {
query = query.Where(v => v.Cylinders <= maxCylinders);
}
}
हम किसी शर्त के आधार पर क्रमबद्ध क्रम को जोड़ सकते हैं:
switch (search.SortingColumn.ToLower()) {
case "make_model":
query = query.OrderBy(v => v.Make).ThenBy(v => v.Model);
break;
case "year":
query = query.OrderBy(v => v.Year);
break;
case "engine_size":
query = query.OrderBy(v => v.EngineSize).ThenBy(v => v.Cylinders);
break;
default:
query = query.OrderBy(v => v.Year); //The default sorting.
}
हमारी क्वेरी को किसी दिए गए बिंदु से शुरू करने के लिए परिभाषित किया जा सकता है:
query = query.Skip(start - 1);
और रिकॉर्ड की एक विशिष्ट संख्या लौटने के लिए परिभाषित:
if (count > -1) {
query = query.Take(count);
}
return query;
}
एक बार जब हमारे पास क्वेरी ऑब्जेक्ट होता है, तो हम परिणामों का मूल्यांकन एक foreach
लूप, या LINQ विधियों में से एक से कर सकते हैं जो मानों का एक सेट लौटाता है, जैसे कि ToList
या ToArray
:
SearchModel sm;
// populate the search model here
// ...
List<VehicleModel> list = BuildQuery(5, sm).ToList();
ज़िप
Zip
एक्सटेंशन विधि दो संग्रह पर कार्य करती है। यह स्थिति के आधार पर दो श्रृंखलाओं में प्रत्येक तत्व को एक साथ जोड़ देता है। Func
उदाहरण के साथ, हम जोड़े में दो C # संग्रह से तत्वों को संभालने के लिए Zip
का उपयोग करते हैं। यदि श्रृंखला आकार में भिन्न है, तो बड़ी श्रृंखला के अतिरिक्त तत्वों को अनदेखा किया जाएगा।
पुस्तक "C # in a संक्षेप में" से एक उदाहरण लेने के लिए:
int[] numbers = { 3, 5, 7 };
string[] words = { "three", "five", "seven", "ignored" };
IEnumerable<string> zip = numbers.Zip(words, (n, w) => n + "=" + w);
आउटपुट:
3 = तीन
5 = पाँच
7 = सात
बाहरी रेंज चर के साथ GroupJoin
Customer[] customers = Customers.ToArray();
Purchase[] purchases = Purchases.ToArray();
var groupJoinQuery =
from c in customers
join p in purchases on c.ID equals p.CustomerID
into custPurchases
select new
{
CustName = c.Name,
custPurchases
};
ElementAt और ElementAtOrDefault
ElementAt
आइटम को इंडेक्स n
पर लौटाएगा। यदि n
गणना योग्य सीमा के भीतर नहीं है, तो एक ArgumentOutOfRangeException
फेंकता है।
int[] numbers = { 1, 2, 3, 4, 5 };
numbers.ElementAt(2); // 3
numbers.ElementAt(10); // throws ArgumentOutOfRangeException
ElementAtOrDefault
इंडेक्स n
पर आइटम लौटाएगा। यदि n
गणनीय की सीमा के भीतर नहीं है, तो एक default(T)
।
int[] numbers = { 1, 2, 3, 4, 5 };
numbers.ElementAtOrDefault(2); // 3
numbers.ElementAtOrDefault(10); // 0 = default(int)
ElementAt
और ElementAtOrDefault
दोनों को तब अनुकूलित किया जाता है जब स्रोत एक IList<T>
और उन मामलों में सामान्य अनुक्रमण का उपयोग किया जाएगा।
ElementAt
लिए ध्यान दें, यदि प्रदान किया गया सूचकांक IList<T>
के आकार से अधिक है, तो सूची को ArgumentOutOfRangeException
फेंकने के लिए (लेकिन तकनीकी रूप से गारंटी नहीं है) चाहिए।
लिनक क्वांटिफायर
क्वांटिफायर ऑपरेशंस एक बूलियन वैल्यू लौटाते हैं यदि किसी क्रम में कुछ या सभी तत्व एक शर्त को पूरा करते हैं। इस आलेख में, हम कुछ सामान्य LINQ ऑब्जेक्ट परिदृश्यों के लिए देखेंगे जहाँ हम इन ऑपरेटरों का उपयोग कर सकते हैं। LINQ में उपयोग किए जा सकने वाले 3 क्वांटिफायर ऑपरेशन हैं:
All
- यह निर्धारित करने के लिए उपयोग किया जाता है कि क्या अनुक्रम में सभी तत्व एक शर्त को पूरा करते हैं। उदाहरण के लिए:
int[] array = { 10, 20, 30 };
// Are all elements >= 10? YES
array.All(element => element >= 10);
// Are all elements >= 20? NO
array.All(element => element >= 20);
// Are all elements < 40? YES
array.All(element => element < 40);
Any
- यह निर्धारित करने के लिए उपयोग किया जाता है कि क्या किसी अनुक्रम में कोई तत्व किसी स्थिति को संतुष्ट करता है। उदाहरण के लिए:
int[] query=new int[] { 2, 3, 4 }
query.Any (n => n == 3);
Contains
- यह निर्धारित करने के लिए उपयोग किया जाता है कि किसी अनुक्रम में एक निर्दिष्ट तत्व है या नहीं। उदाहरण के लिए:
//for int array
int[] query =new int[] { 1,2,3 };
query.Contains(1);
//for string array
string[] query={"Tom","grey"};
query.Contains("Tom");
//for a string
var stringValue="hello";
stringValue.Contains("h");
कई दृश्यों में शामिल होना
Customer
, Purchase
और PurchaseItem
संस्थाओं पर विचार करें:
public class Customer
{
public string Id { get; set } // A unique Id that identifies customer
public string Name {get; set; }
}
public class Purchase
{
public string Id { get; set }
public string CustomerId {get; set; }
public string Description { get; set; }
}
public class PurchaseItem
{
public string Id { get; set }
public string PurchaseId {get; set; }
public string Detail { get; set; }
}
उपरोक्त संस्थाओं के लिए निम्नलिखित नमूना डेटा पर विचार करें:
var customers = new List<Customer>()
{
new Customer() {
Id = Guid.NewGuid().ToString(),
Name = "Customer1"
},
new Customer() {
Id = Guid.NewGuid().ToString(),
Name = "Customer2"
}
};
var purchases = new List<Purchase>()
{
new Purchase() {
Id = Guid.NewGuid().ToString(),
CustomerId = customers[0].Id,
Description = "Customer1-Purchase1"
},
new Purchase() {
Id = Guid.NewGuid().ToString(),
CustomerId = customers[0].Id,
Description = "Customer1-Purchase2"
},
new Purchase() {
Id = Guid.NewGuid().ToString(),
CustomerId = customers[1].Id,
Description = "Customer2-Purchase1"
},
new Purchase() {
Id = Guid.NewGuid().ToString(),
CustomerId = customers[1].Id,
Description = "Customer2-Purchase2"
}
};
var purchaseItems = new List<PurchaseItem>()
{
new PurchaseItem() {
Id = Guid.NewGuid().ToString(),
PurchaseId= purchases[0].Id,
Detail = "Purchase1-PurchaseItem1"
},
new PurchaseItem() {
Id = Guid.NewGuid().ToString(),
PurchaseId= purchases[1].Id,
Detail = "Purchase2-PurchaseItem1"
},
new PurchaseItem() {
Id = Guid.NewGuid().ToString(),
PurchaseId= purchases[1].Id,
Detail = "Purchase2-PurchaseItem2"
},
new PurchaseItem() {
Id = Guid.NewGuid().ToString(),
PurchaseId= purchases[3].Id,
Detail = "Purchase3-PurchaseItem1"
}
};
अब, linq क्वेरी के नीचे विचार करें:
var result = from c in customers
join p in purchases on c.Id equals p.CustomerId // first join
join pi in purchaseItems on p.Id equals pi.PurchaseId // second join
select new
{
c.Name, p.Description, pi.Detail
};
उपरोक्त क्वेरी के परिणाम का उत्पादन करने के लिए:
foreach(var resultItem in result)
{
Console.WriteLine($"{resultItem.Name}, {resultItem.Description}, {resultItem.Detail}");
}
क्वेरी का आउटपुट होगा:
Customer1, Customer1-Purchase1, Purchase1-PurchaseItem1
Customer1, Customer1-Purchase2, Purchase2-PurchaseItem1
Customer1, Customer1-Purchase2, Purchase2-PurchaseItem2
ग्राहक 2, ग्राहक 2-खरीद 2, खरीद 3-खरीद 1
कई कुंजियों पर जुड़ना
PropertyInfo[] stringProps = typeof (string).GetProperties();//string properties
PropertyInfo[] builderProps = typeof(StringBuilder).GetProperties();//stringbuilder properties
var query =
from s in stringProps
join b in builderProps
on new { s.Name, s.PropertyType } equals new { b.Name, b.PropertyType }
select new
{
s.Name,
s.PropertyType,
StringToken = s.MetadataToken,
StringBuilderToken = b.MetadataToken
};
ध्यान दें कि उपरोक्त प्रकार के अनाम प्रकारों में समान गुण join
चाहिए क्योंकि वस्तुओं को समान माना जाता है, यदि उनके सभी गुण समान हों। अन्यथा क्वेरी संकलित नहीं होगी।
फंक के साथ चयन करें चयनकर्ता - तत्वों की रैंकिंग प्राप्त करने के लिए उपयोग करें
के भार के की पर Select
विस्तार तरीकों में भी गुजरता index
संग्रह किया जा रहा में वर्तमान आइटम का select
एड। ये इसके कुछ उपयोग हैं।
आइटम की "पंक्ति संख्या" प्राप्त करें
var rowNumbers = collection.OrderBy(item => item.Property1)
.ThenBy(item => item.Property2)
.ThenByDescending(item => item.Property3)
.Select((item, index) => new { Item = item, RowNumber = index })
.ToList();
अपने समूह के भीतर एक आइटम के पद जाओ
var rankInGroup = collection.GroupBy(item => item.Property1)
.OrderBy(group => group.Key)
.SelectMany(group => group.OrderBy(item => item.Property2)
.ThenByDescending(item => item.Property3)
.Select((item, index) => new
{
Item = item,
RankInGroup = index
})).ToList();
समूहों की रैंकिंग प्राप्त करें (Oracle में dense_rank के रूप में भी जाना जाता है)
var rankOfBelongingGroup = collection.GroupBy(item => item.Property1)
.OrderBy(group => group.Key)
.Select((group, index) => new
{
Items = group,
Rank = index
})
.SelectMany(v => v.Items, (s, i) => new
{
Item = i,
DenseRank = s.Rank
}).ToList();
इसके परीक्षण के लिए आप इसका उपयोग कर सकते हैं:
public class SomeObject
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public int Property3 { get; set; }
public override string ToString()
{
return string.Join(", ", Property1, Property2, Property3);
}
}
और डेटा:
List<SomeObject> collection = new List<SomeObject>
{
new SomeObject { Property1 = 1, Property2 = 1, Property3 = 1},
new SomeObject { Property1 = 1, Property2 = 2, Property3 = 1},
new SomeObject { Property1 = 1, Property2 = 2, Property3 = 2},
new SomeObject { Property1 = 2, Property2 = 1, Property3 = 1},
new SomeObject { Property1 = 2, Property2 = 2, Property3 = 1},
new SomeObject { Property1 = 2, Property2 = 2, Property3 = 1},
new SomeObject { Property1 = 2, Property2 = 3, Property3 = 1}
};
TakeWhile
जब तक स्थिति सत्य होती है तब तक TakeWhile
एक क्रम से तत्वों को लौटाता है
int[] list = { 1, 10, 40, 50, 44, 70, 4 };
var result = list.TakeWhile(item => item < 50).ToList();
// result = { 1, 10, 40 }
योग
Enumerable.Sum
विस्तार विधि संख्यात्मक मूल्यों के योग की गणना करती है।
यदि संग्रह के तत्व स्वयं संख्या हैं, तो आप सीधे राशि की गणना कर सकते हैं।
int[] numbers = new int[] { 1, 4, 6 };
Console.WriteLine( numbers.Sum() ); //outputs 11
यदि तत्व का प्रकार एक जटिल प्रकार है, तो आप उस मूल्य को निर्दिष्ट करने के लिए एक लंबोदर अभिव्यक्ति का उपयोग कर सकते हैं जिसे गणना की जानी चाहिए:
var totalMonthlySalary = employees.Sum( employee => employee.MonthlySalary );
सम विस्तार विधि निम्न प्रकारों से गणना कर सकती है:
- int32
- Int64
- एक
- दोहरा
- दशमलव
यदि आपके संग्रह में अशक्त प्रकार हैं, तो आप अशक्त तत्वों के लिए एक डिफ़ॉल्ट मान सेट करने के लिए नल-कोलेसिंग ऑपरेटर का उपयोग कर सकते हैं:
int?[] numbers = new int?[] { 1, null, 6 };
Console.WriteLine( numbers.Sum( number => number ?? 0 ) ); //outputs 7
देखने के लिए
ToLookup एक डेटा संरचना देता है जो अनुक्रमण की अनुमति देता है। यह एक विस्तार विधि है। यह एक ILookup उदाहरण का उत्पादन करता है जिसे फॉर्च-लूप का उपयोग करके अनुक्रमित या एनुमरेट किया जा सकता है। प्रविष्टियों को प्रत्येक कुंजी में समूह में जोड़ा जाता है। - डॉटनेटपर्ल्स
string[] array = { "one", "two", "three" };
//create lookup using string length as key
var lookup = array.ToLookup(item => item.Length);
//join the values whose lengths are 3
Console.WriteLine(string.Join(",",lookup[3]));
//output: one,two
एक और उदाहरण:
int[] array = { 1,2,3,4,5,6,7,8 };
//generate lookup for odd even numbers (keys will be 0 and 1)
var lookup = array.ToLookup(item => item % 2);
//print even numbers after joining
Console.WriteLine(string.Join(",",lookup[0]));
//output: 2,4,6,8
//print odd numbers after joining
Console.WriteLine(string.Join(",",lookup[1]));
//output: 1,3,5,7
IEnumerable के लिए अपने खुद के Linq ऑपरेटरों का निर्माण
लिनक के बारे में एक बड़ी बात यह है कि इसका विस्तार करना इतना आसान है। आपको बस एक एक्सटेंशन विधि बनाने की आवश्यकता है जिसका तर्क IEnumerable<T>
।
public namespace MyNamespace
{
public static class LinqExtensions
{
public static IEnumerable<List<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
{
var batch = new List<T>();
foreach (T item in source)
{
batch.Add(item);
if (batch.Count == batchSize)
{
yield return batch;
batch = new List<T>();
}
}
if (batch.Count > 0)
yield return batch;
}
}
}
यह उदाहरण IEnumerable<T>
में आइटम को एक निश्चित आकार की सूची में विभाजित करता है, अंतिम सूची जिसमें शेष आइटम हैं। ध्यान दें कि जिस ऑब्जेक्ट को एक्सटेंशन विधि लागू किया गया है वह this
तर्क (तर्क source
) में this
कीवर्ड का उपयोग करके प्रारंभिक तर्क के रूप में कैसे पारित किया जाता है। तब yield
कीवर्ड का उपयोग उस बिंदु से निष्पादन के बाद जारी रखने से पहले आउटपुट IEnumerable<T>
में अगले आइटम को आउटपुट करने के लिए किया जाता है ( उपज कीवर्ड देखें)।
आपके कोड में इस उदाहरण का उपयोग किया जाएगा:
//using MyNamespace;
var items = new List<int> { 2, 3, 4, 5, 6 };
foreach (List<int> sublist in items.Batch(3))
{
// do something
}
पहले लूप पर, सब लिस्ट {2, 3, 4}
और दूसरी {5, 6}
।
कस्टम LinQ विधियों को मानक LinQ विधियों के साथ भी जोड़ा जा सकता है। उदाहरण के लिए:
//using MyNamespace;
var result = Enumerable.Range(0, 13) // generate a list
.Where(x => x%2 == 0) // filter the list or do something other
.Batch(3) // call our extension method
.ToList() // call other standard methods
यह प्रश्न 3: {0, 2, 4}, {6, 8, 10}, {12}
आकार के साथ बैचों में वर्गीकृत संख्याओं को भी लौटाएगा।
याद रखें कि आपको using MyNamespace;
करने की आवश्यकता है using MyNamespace;
विस्तार विधि का उपयोग करने में सक्षम होने के लिए लाइन।
नेस्टेड छोरों के बजाय SelectMany का उपयोग करना
2 सूची दी
var list1 = new List<string> { "a", "b", "c" };
var list2 = new List<string> { "1", "2", "3", "4" };
यदि आप सभी क्रमपरिवर्तन का उत्पादन करना चाहते हैं तो आप नेस्टेड छोरों का उपयोग कर सकते हैं
var result = new List<string>();
foreach (var s1 in list1)
foreach (var s2 in list2)
result.Add($"{s1}{s2}");
SelectMany का उपयोग करके आप के रूप में एक ही ऑपरेशन कर सकते हैं
var result = list1.SelectMany(x => list2.Select(y => $"{x}{y}", x, y)).ToList();
किसी भी और पहले (OrDefault) - सबसे अच्छा अभ्यास
मैं Any
और FirstOrDefault
क्या करता है की व्याख्या नहीं करेंगे क्योंकि उनके बारे में पहले से ही दो अच्छे उदाहरण हैं। अधिक जानकारी के लिए कोई भी और पहले, FirstOrDefault, Last, LastOrDefault, Single और SingleOrDefault देखें।
एक पैटर्न जिसे मैं अक्सर कोड में देखता हूं जिसे टाला जाना चाहिए
if (myEnumerable.Any(t=>t.Foo == "Bob"))
{
var myFoo = myEnumerable.First(t=>t.Foo == "Bob");
//Do stuff
}
इसे इस तरह और अधिक कुशलता से लिखा जा सकता था
var myFoo = myEnumerable.FirstOrDefault(t=>t.Foo == "Bob");
if (myFoo != null)
{
//Do stuff
}
दूसरे उदाहरण का उपयोग करके, संग्रह केवल एक बार खोजा जाता है और पहले वाले के समान परिणाम देता है। Single
लिए एक ही विचार लागू किया जा सकता है।
ग्रुपबी सम और काउंट
चलो एक नमूना वर्ग लेते हैं:
public class Transaction
{
public string Category { get; set; }
public DateTime Date { get; set; }
public decimal Amount { get; set; }
}
अब, लेन-देन की सूची पर विचार करते हैं:
var transactions = new List<Transaction>
{
new Transaction { Category = "Saving Account", Amount = 56, Date = DateTime.Today.AddDays(1) },
new Transaction { Category = "Saving Account", Amount = 10, Date = DateTime.Today.AddDays(-10) },
new Transaction { Category = "Credit Card", Amount = 15, Date = DateTime.Today.AddDays(1) },
new Transaction { Category = "Credit Card", Amount = 56, Date = DateTime.Today },
new Transaction { Category = "Current Account", Amount = 100, Date = DateTime.Today.AddDays(5) },
};
यदि आप श्रेणीवार राशि और गणना की गणना करना चाहते हैं, तो आप GroupBy का उपयोग इस प्रकार कर सकते हैं:
var summaryApproach1 = transactions.GroupBy(t => t.Category)
.Select(t => new
{
Category = t.Key,
Count = t.Count(),
Amount = t.Sum(ta => ta.Amount),
}).ToList();
Console.WriteLine("-- Summary: Approach 1 --");
summaryApproach1.ForEach(
row => Console.WriteLine($"Category: {row.Category}, Amount: {row.Amount}, Count: {row.Count}"));
वैकल्पिक रूप से, आप इसे एक चरण में कर सकते हैं:
var summaryApproach2 = transactions.GroupBy(t => t.Category, (key, t) =>
{
var transactionArray = t as Transaction[] ?? t.ToArray();
return new
{
Category = key,
Count = transactionArray.Length,
Amount = transactionArray.Sum(ta => ta.Amount),
};
}).ToList();
Console.WriteLine("-- Summary: Approach 2 --");
summaryApproach2.ForEach(
row => Console.WriteLine($"Category: {row.Category}, Amount: {row.Amount}, Count: {row.Count}"));
उपरोक्त दोनों प्रश्नों के लिए आउटपुट समान होगा:
श्रेणी: बचत खाता, राशि: 66, गणना: 2
श्रेणी: क्रेडिट कार्ड, राशि: 71, गणना: 2
श्रेणी: चालू खाता, राशि: १००, गणना: १
रिवर्स
- तत्वों के क्रम को एक क्रम में सम्मिलित करता है।
- यदि कोई आइटम नहीं है तो एक
ArgumentNullException: source is null.
फेंकता हैArgumentNullException: source is null.
उदाहरण:
// Create an array.
int[] array = { 1, 2, 3, 4 }; //Output:
// Call reverse extension method on the array. //4
var reverse = array.Reverse(); //3
// Write contents of array to screen. //2
foreach (int value in reverse) //1
Console.WriteLine(value);
रिमाइबर कि Reverse()
आपके LINQ कथनों की श्रृंखला क्रम के आधार पर अलग-अलग काम कर सकता है।
//Create List of chars
List<int> integerlist = new List<int>() { 1, 2, 3, 4, 5, 6 };
//Reversing the list then taking the two first elements
IEnumerable<int> reverseFirst = integerlist.Reverse<int>().Take(2);
//Taking 2 elements and then reversing only thos two
IEnumerable<int> reverseLast = integerlist.Take(2).Reverse();
//reverseFirst output: 6, 5
//reverseLast output: 2, 1
रिवर्स () सब कुछ बफर करके काम करता है फिर उसके पीछे से गुजरें, चुड़ैल बहुत कुशल नहीं है, लेकिन न तो उस दृष्टिकोण से ऑर्डरबाय है।
LINQ-to-Objects में बफरिंग ऑपरेशंस (Reverse, OrderBy, GroupBy, आदि) और नॉन-बफरिंग ऑपरेशंस (कहां, टेक, स्किप, आदि) हैं।
उदाहरण: गैर-बफरिंग रिवर्स एक्सट्रेशन
public static IEnumerable<T> Reverse<T>(this IList<T> list) {
for (int i = list.Count - 1; i >= 0; i--)
yield return list[i];
}
यह विधि समस्याओं का सामना कर सकती है यदि पुनरावृति करते समय आप सूची को संशोधित करते हैं।
गणना करने योग्य
IEnumerable <T> इंटरफ़ेस सभी सामान्य प्रगणकों के लिए आधार इंटरफ़ेस है और LINQ को समझने का एक महत्वपूर्ण हिस्सा है। इसके मूल में, यह अनुक्रम का प्रतिनिधित्व करता है।
यह अंतर्निहित इंटरफ़ेस सभी संग्रह जैसे कि <<> , Array , List <T> , Dictionary <TKey, TValue> Class , और HashSet <T> द्वारा प्राप्त किया जाता है ।
अनुक्रम का प्रतिनिधित्व करने के अलावा, कोई भी वर्ग जो IEnumerable <T> से विरासत में मिला है, उसे IEnumerator <T> प्रदान करना होगा। प्रगणक प्रगणक के लिए पुनरावृत्ति को उजागर करता है, और ये दो परस्पर जुड़े इंटरफेस और विचार "कहे जाने योग्य" की गणना का स्रोत हैं।
"एनुमरेबल एनुमरेटिंग" एक महत्वपूर्ण वाक्यांश है। गणना करने योग्य है कि कैसे इसे पुनरावृत्त किया जाए, इसके लिए कोई संरचना नहीं है, यह किसी भी भौतिक वस्तुओं को नहीं रखता है। उदाहरण के लिए, जब छँटाई होती है, तो एक गणनीय क्षेत्र को छाँटने के लिए मापदंड रख सकता है, लेकिन उपयोग करना .OrderBy()
अपने आप में एक IEnumerable <T> लौटा देगा जो केवल यह जानता है कि कैसे .OrderBy()
। एक कॉल का उपयोग करना, जो ऑब्जेक्ट्स को भौतिक रूप में सेट के रूप में पुनरावृत्त करेगा, एन्यूमरेटिंग (उदाहरण के लिए .ToList()
) के रूप में जाना जाता है। गणना प्रक्रिया श्रृंखला के माध्यम से स्थानांतरित करने के लिए और संबंधित वस्तुओं (क्रम में, फ़िल्टर्ड, आदि) को वापस करने के लिए कैसे प्रयोग की जाने वाली परिभाषा का उपयोग करेगी।
केवल एक बार गणना करने योग्य होने के बाद यह वस्तुओं के भौतिककरण का कारण बनता है, जो तब होता है जब समय की जटिलता जैसे मेट्रिक्स (श्रृंखला आकार से कितना समय लेना चाहिए) और स्थानिक जटिलता (श्रृंखला के आकार से संबंधित इसे कितनी जगह का उपयोग करना चाहिए)। मापा जाए।
IEnumerable <T> से विरासत में मिली अपनी खुद की क्लास बनाना अंतर्निहित श्रृंखला के आधार पर थोड़ा जटिल हो सकता है जिसे गणना करने की आवश्यकता होती है। सामान्य तौर पर मौजूदा जेनेरिक संग्रहों में से एक का उपयोग करना सबसे अच्छा है। उस ने कहा, यह भी अंतर्निहित संरचना के रूप में एक परिभाषित सरणी के बिना IEnumerable <T> इंटरफ़ेस से विरासत में संभव है।
उदाहरण के लिए, अंतर्निहित अनुक्रम के रूप में फाइबोनैचि श्रृंखला का उपयोग करना। ध्यान दें कि करने के लिए कॉल Where
बस बनाता है एक IEnumerable
, और यह गणना करने में एक फोन है कि गणनीय किया जाता है कि कोई भी मान materialized कर रहे हैं जब तक नहीं है।
void Main()
{
Fibonacci Fibo = new Fibonacci();
IEnumerable<long> quadrillionplus = Fibo.Where(i => i > 1000000000000);
Console.WriteLine("Enumerable built");
Console.WriteLine(quadrillionplus.Take(2).Sum());
Console.WriteLine(quadrillionplus.Skip(2).First());
IEnumerable<long> fibMod612 = Fibo.OrderBy(i => i % 612);
Console.WriteLine("Enumerable built");
Console.WriteLine(fibMod612.First());//smallest divisible by 612
}
public class Fibonacci : IEnumerable<long>
{
private int max = 90;
//Enumerator called typically from foreach
public IEnumerator GetEnumerator() {
long n0 = 1;
long n1 = 1;
Console.WriteLine("Enumerating the Enumerable");
for(int i = 0; i < max; i++){
yield return n0+n1;
n1 += n0;
n0 = n1-n0;
}
}
//Enumerable called typically from linq
IEnumerator<long> IEnumerable<long>.GetEnumerator() {
long n0 = 1;
long n1 = 1;
Console.WriteLine("Enumerating the Enumerable");
for(int i = 0; i < max; i++){
yield return n0+n1;
n1 += n0;
n0 = n1-n0;
}
}
}
उत्पादन
Enumerable built
Enumerating the Enumerable
4052739537881
Enumerating the Enumerable
4052739537881
Enumerable built
Enumerating the Enumerable
14930352
दूसरे सेट (fibMod612) में ताकत यह है कि भले ही हमने अपने पूरे सेट को फाइबोनैचि संख्याओं को ऑर्डर करने के लिए कॉल किया हो, क्योंकि केवल एक मान का उपयोग किया गया था। केवल .First()
समय जटिलता ओ थी (n) केवल 1 मान के रूप में आर्डरिंग एल्गोरिथम के निष्पादन के दौरान तुलना करने की आवश्यकता है। ऐसा इसलिए है क्योंकि हमारे एन्यूमरेटर ने केवल 1 मूल्य मांगा था, और इसलिए पूरे एन्यूमरेबल को भौतिक बनाना नहीं था। अगर हमने इस्तेमाल किया होता। तो .Take(5)
बजाय .First()
.Take(5)
एन्यूमरेटर ने 5 मान मांगे होते, और अधिक से अधिक 5 मूल्यों को भौतिक बनाना होता। पूरे सेट को ऑर्डर करने और फिर पहले 5 मान लेने की आवश्यकता के मुकाबले, बहुत सारे निष्पादन समय और स्थान को बचाता है।
द्वारा आदेश
एक निर्दिष्ट मूल्य से एक संग्रह का आदेश।
जब मान एक पूर्णांक होता है , तो यह डबल या फ्लोट न्यूनतम मूल्य के साथ शुरू होता है, जिसका अर्थ है कि आपको शून्य से पहले नकारात्मक मान मिलते हैं, और सकारात्मक मानों के बाद (उदाहरण 1 देखें)।
जब आप एक चार्ट द्वारा आदेश देते हैं तो विधि संग्रह को क्रमबद्ध करने के लिए वर्णों के एससीआई मूल्यों की तुलना करती है (उदाहरण 2 देखें)।
जब आप स्ट्रिंग्स को क्रमबद्ध करते हैं तो ऑर्डरबाय विधि उनके कल्चरइन्फो पर एक नज़र डालकर उनकी तुलना करती है लेकिन सामान्य अक्षर (ए, बी, सी ...) में पहले अक्षर से शुरू होती है।
इस तरह के आदेश को आरोही कहा जाता है, यदि आप इसे दूसरे तरीके से चाहते हैं तो आपको अवरोही की जरूरत है (देखें ऑर्डरबायस्केंडिंग)।
उदाहरण 1:
int[] numbers = {2, 1, 0, -1, -2};
IEnumerable<int> ascending = numbers.OrderBy(x => x);
// returns {-2, -1, 0, 1, 2}
उदाहरण 2:
char[] letters = {' ', '!', '?', '[', '{', '+', '1', '9', 'a', 'A', 'b', 'B', 'y', 'Y', 'z', 'Z'};
IEnumerable<char> ascending = letters.OrderBy(x => x);
// returns { ' ', '!', '+', '1', '9', '?', 'A', 'B', 'Y', 'Z', '[', 'a', 'b', 'y', 'z', '{' }
उदाहरण:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
var people = new[]
{
new Person {Name = "Alice", Age = 25},
new Person {Name = "Bob", Age = 21},
new Person {Name = "Carol", Age = 43}
};
var youngestPerson = people.OrderBy(x => x.Age).First();
var name = youngestPerson.Name; // Bob
OrderByDescending
एक निर्दिष्ट मूल्य से एक संग्रह का आदेश।
जब मान एक पूर्णांक होता है , तो यह डबल या फ्लोट होता है, जो अधिकतम मान से शुरू होता है, जिसका अर्थ है कि आपको पहले सकारात्मक मान मिलता है, शून्य से और नकारात्मक मानों के बाद (उदाहरण 1 देखें)।
जब आप एक चार्ट द्वारा आदेश देते हैं तो विधि संग्रह को क्रमबद्ध करने के लिए वर्णों के एससीआई मूल्यों की तुलना करती है (उदाहरण 2 देखें)।
जब आप स्ट्रिंग्स को क्रमबद्ध करते हैं तो ऑर्डरबी विधि उनके कल्चरइन्फो पर एक नज़र डालकर उनकी तुलना करती है लेकिन सामान्य अक्षर (z, y, x, ...) में अंतिम अक्षर से शुरू होती है।
इस तरह के आदेश को अवरोही कहा जाता है, यदि आप इसे दूसरे तरीके से चाहते हैं तो आपको आरोही की जरूरत है (देखें ऑर्डरबी)।
उदाहरण 1:
int[] numbers = {-2, -1, 0, 1, 2};
IEnumerable<int> descending = numbers.OrderByDescending(x => x);
// returns {2, 1, 0, -1, -2}
उदाहरण 2:
char[] letters = {' ', '!', '?', '[', '{', '+', '1', '9', 'a', 'A', 'b', 'B', 'y', 'Y', 'z', 'Z'};
IEnumerable<char> descending = letters.OrderByDescending(x => x);
// returns { '{', 'z', 'y', 'b', 'a', '[', 'Z', 'Y', 'B', 'A', '?', '9', '1', '+', '!', ' ' }
उदाहरण 3:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
var people = new[]
{
new Person {Name = "Alice", Age = 25},
new Person {Name = "Bob", Age = 21},
new Person {Name = "Carol", Age = 43}
};
var oldestPerson = people.OrderByDescending(x => x.Age).First();
var name = oldestPerson.Name; // Carol
concat
दो संग्रह जोड़ता है (डुप्लिकेट को हटाए बिना)
List<int> foo = new List<int> { 1, 2, 3 };
List<int> bar = new List<int> { 3, 4, 5 };
// Through Enumerable static class
var result = Enumerable.Concat(foo, bar).ToList(); // 1,2,3,3,4,5
// Through extension method
var result = foo.Concat(bar).ToList(); // 1,2,3,3,4,5
शामिल
MSDN:
निर्धारित करता है कि किसी अनुक्रम में निर्दिष्ट
IEqualityComparer<T>
का उपयोग करके एक निर्दिष्ट तत्व है या नहीं
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var result1 = numbers.Contains(4); // true
var result2 = numbers.Contains(8); // false
List<int> secondNumberCollection = new List<int> { 4, 5, 6, 7 };
// Note that can use the Intersect method in this case
var result3 = secondNumberCollection.Where(item => numbers.Contains(item)); // will be true only for 4,5
उपयोगकर्ता परिभाषित वस्तु का उपयोग करना:
public class Person
{
public string Name { get; set; }
}
List<Person> objects = new List<Person>
{
new Person { Name = "Nikki"},
new Person { Name = "Gilad"},
new Person { Name = "Phil"},
new Person { Name = "John"}
};
//Using the Person's Equals method - override Equals() and GetHashCode() - otherwise it
//will compare by reference and result will be false
var result4 = objects.Contains(new Person { Name = "Phil" }); // true
Enumerable.Contains(value, comparer)
अधिभार का उपयोग करना:
public class Compare : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.Name == y.Name;
}
public int GetHashCode(Person codeh)
{
return codeh.Name.GetHashCode();
}
}
var result5 = objects.Contains(new Person { Name = "Phil" }, new Compare()); // true
का एक स्मार्ट उपयोग Contains
कई को बदलने के लिए होगा if
एक को खंड Contains
कॉल।
इसलिए ऐसा करने के बजाय:
if(status == 1 || status == 3 || status == 4)
{
//Do some business operation
}
else
{
//Do something else
}
यह करो:
if(new int[] {1, 3, 4 }.Contains(status)
{
//Do some business operaion
}
else
{
//Do something else
}