লিনক-এ এনিউমারেবল.জিপ এক্সটেনশন পদ্ধতির ব্যবহার কী?


130

Enumerable.Zipলিংকে এক্সটেনশন পদ্ধতির ব্যবহার কী ?


2
আপনি কি এটি উল্লেখ করছেন: এমএসডিএন.মাইক্রোসফটকম /en-us/library/dd267698.aspx ? - তুমি অর্জন করার জন্য কি চেষ্টা করতেছ?

13
এটি জিপারের দু'পক্ষের মতো একসাথে আসার মতো।
কেভিন পানকো

উত্তর:


191

জিপ অপারেটর একটি নির্দিষ্ট নির্বাচক ফাংশন ব্যবহার করে দুটি সিকোয়েন্সের সংশ্লিষ্ট উপাদানগুলিকে মার্জ করে।

var letters= new string[] { "A", "B", "C", "D", "E" };
var numbers= new int[] { 1, 2, 3 };
var q = letters.Zip(numbers, (l, n) => l + n.ToString());
foreach (var s in q)
    Console.WriteLine(s);

Ouput

A1
B2
C3

41
আমি এই উত্তরটি পছন্দ করি কারণ এটি এমএসডিএন ডকুমেন্টেশনের
DLeh

2
আমি যদি জিপটি চালিয়ে যেতে চাই যেখানে একটি তালিকা উপাদানের বাইরে চলে যায়? এই ক্ষেত্রে সংক্ষিপ্ত তালিকা উপাদানটির ডিফল্ট মান নেওয়া উচিত। এ ক্ষেত্রে আউটপুট এ 1, বি 2, সি 3, ডি 0, ই 0 হবে।
লিয়াং

2
@ লিয়ালিং দুটি পছন্দ: ক) আপনার নিজস্ব Zipবিকল্প লিখুন । বি) একটি পদ্ধতি লিখুন yield returnখাটো তালিকাটির প্রতিটি উপাদান, এবং তারপর অবিরত yield returning defaultঅনির্দিষ্টকালের তারপরে। (বিকল্প বি আপনি আগাম যা তালিকা খাটো জানতে প্রয়োজন।)
jpaugh

105

Zipএকটিতে দুটি সিকোয়েন্স যুক্ত করার জন্য। উদাহরণস্বরূপ, যদি আপনার ক্রম থাকে

1, 2, 3

এবং

10, 20, 30

এবং আপনি যে ক্রমটি চান তা প্রতিটি ক্রমটিতে একই অবস্থানে একই উপাদানের গুণনের ফলাফল

10, 40, 90

তুমি বলতে পার

var left = new[] { 1, 2, 3 };
var right = new[] { 10, 20, 30 };
var products = left.Zip(right, (m, n) => m * n);

এটিকে "জিপ" বলা হয় কারণ আপনি একটি জিপরের বাম দিক হিসাবে একটি অনুক্রম এবং অন্য ক্রমটি জিপারের ডান দিক হিসাবে মনে করেন এবং জিপ অপারেটর দুটি পক্ষকে এক সাথে দাঁত বন্ধ করে টেনে আনবে ( অনুক্রমের উপাদানগুলি) যথাযথভাবে।


8
এখানে অবশ্যই সেরা ব্যাখ্যা।
ম্যাক্সিম গের্স্কোভিচ

2
জিপার উদাহরণ পছন্দ। এটা খুব স্বাভাবিক ছিল। আমার প্রাথমিক ধারণাটি হ'ল যদি এটির গতির সাথে কিছু করার থাকে বা এর মতো কিছু থাকে যেন আপনি নিজের গাড়ীর কোনও রাস্তায় জিপ করেন।
আরবিটি

23

এটি দুটি অনুক্রমের মাধ্যমে পুনরাবৃত্তি করে এবং তাদের উপাদানগুলিকে একের পর এক একক নতুন অনুক্রমের সাথে সংযুক্ত করে। সুতরাং আপনি সিকোয়েন্স এ এর ​​একটি উপাদান নিবেন, সিকোয়েন্স বি থেকে আনুষঙ্গিক উপাদানটির সাথে এটি রূপান্তর করুন, এবং ফলাফলটি ক্রম সি এর উপাদান গঠন করে forms

এটি সম্পর্কে চিন্তা করার এক উপায় হ'ল এটির অনুরূপ Select, একক সংগ্রহ থেকে আইটেমগুলিকে রূপান্তর না করে, এটি একবারে দুটি সংগ্রহের উপর কাজ করে।

পদ্ধতিটিতে এমএসডিএন নিবন্ধ থেকে :

int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };

var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);

foreach (var item in numbersAndWords)
    Console.WriteLine(item);

// This code produces the following output:

// 1 one
// 2 two
// 3 three

আপনি যদি বাধ্যতামূলক কোডটিতে এটি করতে থাকেন তবে আপনি সম্ভবত এটির মতো কিছু করতেন:

for (int i = 0; i < numbers.Length && i < words.Length; i++)
{
    numbersAndWords.Add(numbers[i] + " " + words[i]);
}

অথবা যদি লিনকিউ না থাকে তবে Zipআপনি এটি করতে পারেন:

var numbersAndWords = numbers.Select(
                          (num, i) => num + " " + words[i]
                      );

আপনি যখন সরল, অ্যারে-জাতীয় তালিকায় একই দৈর্ঘ্য এবং শৃঙ্খলা সহ প্রতিটি এবং একই সামগ্রীর সেটগুলির পৃথক সম্পত্তি বর্ণনা করছেন তখন ডেটা ছড়িয়ে পড়ে তখন এটি কার্যকর হয়। Zipসেই ডেটাগুলির টুকরাগুলি আরও সুসংগত কাঠামোতে বুনতে আপনাকে সহায়তা করে।

সুতরাং আপনার যদি রাষ্ট্রের নামের একটি অ্যারে এবং তাদের সংক্ষিপ্তসারগুলির আর একটি অ্যারে থাকে তবে আপনি সেগুলি এই জাতীয় Stateশ্রেণিতে সমষ্টি করতে পারেন:

IEnumerable<State> GetListOfStates(string[] stateNames, int[] statePopulations)
{
    return stateNames.Zip(statePopulations, 
                          (name, population) => new State()
                          {
                              Name = name,
                              Population = population
                          });
}

আমি এই Select
উত্তরটিও

17

নামটি Zipআপনাকে ফেলে দিতে দেবেন না । জিপ করা যেমন কোনও ফাইল বা ফোল্ডারে জিপ করা (সংকোচনের) সাথে কিছু করার নেই। এটি আসলে পোশাকটির একটি জিপার কীভাবে কাজ করে তার থেকে এটির নামটি পায়: পোশাকগুলিতে জিপারের 2 টি পক্ষ থাকে এবং প্রতিটি পক্ষেই দাঁতগুলির একগুচ্ছ থাকে। আপনি যখন এক দিকে যান, জিপার উভয় পক্ষের গণনা করে (ভ্রমণ করে) এবং দাঁত কাটা দ্বারা জিপারটি বন্ধ করে দেয়। আপনি যখন অন্য দিকে যান তখন দাঁতগুলি খোলে। আপনি হয় একটি খোলা বা বন্ধ জিপার দিয়ে শেষ করুন।

এটি Zipপদ্ধতির সাথে একই ধারণা । আমাদের দুটি সংগ্রহ আছে যেখানে একটি উদাহরণ বিবেচনা করুন। একটিতে অক্ষর রয়েছে এবং অপরটিতে একটি খাদ্য সামগ্রীর নাম রয়েছে যা সেই চিঠিটি দিয়ে শুরু হয়। স্পষ্টতার উদ্দেশ্যে আমি তাদের কল করছি leftSideOfZipperএবং rightSideOfZipper। কোডটি এখানে।

var leftSideOfZipper = new List<string> { "A", "B", "C", "D", "E" };
var rightSideOfZipper = new List<string> { "Apple", "Banana", "Coconut", "Donut" };

আমাদের কাজ হ'ল এমন একটি সংগ্রহ তৈরি করা যাতে ফলের অক্ষরটি একটি :এবং এর নামের সাথে পৃথক করা থাকে । এটার মত:

A : Apple
B : Banana
C : Coconut
D : Donut

Zipউদ্ধার করতে. আমাদের জিপার পরিভাষাটি ধরে রাখতে আমরা এই ফলাফলটি কল করব closedZipperএবং বাম জিপারের আইটেমগুলি আমরা কল করব leftToothএবং ডান দিকটি আমরা righToothস্পষ্ট কারণে কল করব :

var closedZipper = leftSideOfZipper
   .Zip(rightSideOfZipper, (leftTooth, rightTooth) => leftTooth + " : " + rightTooth).ToList();

উপরের অংশে আমরা জিপারের বাম দিক এবং জিপারের ডানদিকে গণনা করছি (ভ্রমণ) করছি এবং প্রতিটি দাঁতে অপারেশন করছি। আমরা যে অপারেশনটি করছি তা হ'ল বাম দাঁতকে (খাদ্য বর্ণ) একটি :এবং তারপরে ডান দাঁত (খাবারের নাম) দিয়ে সংশ্লেষ করা। আমরা এই কোডটি ব্যবহার করে এটি করি:

(leftTooth, rightTooth) => leftTooth + " : " + rightTooth)

শেষ ফলাফলটি হ'ল:

A : Apple
B : Banana
C : Coconut
D : Donut

শেষ চিঠিটি কি হয়েছে?

আপনি যদি সত্যিকারের জামার জিপার এবং একপাশে গণনা করছেন (টানছেন), বাম দিক বা ডান দিকটি বিবেচনা না করে, অন্য পাশের চেয়ে দাঁত কম রয়েছে, তবে কী হবে? আচ্ছা জিপারটি সেখানেই থামবে। Zipপদ্ধতি ঠিক একই কাজ করতে হবে: এটা বন্ধ হবে একবার এটি উভয় পাশে শেষ আইটেম পৌঁছেছে। আমাদের ক্ষেত্রে ডান পাশে দাঁত কম রয়েছে (খাবারের নাম) তাই এটি "ডোনাট" এ থামবে।


1
+1 টি। হ্যাঁ, "জিপ" নামটি প্রথমে বিভ্রান্তিকর হতে পারে। সম্ভবত "ইন্টারলিও" বা "ওয়েভ" পদ্ধতির আরও বর্ণনামূলক নাম হত।
বেকন

1
@ ব্যাকন হ্যাঁ তবে তারপরে আমি আমার জিপার উদাহরণটি ব্যবহার করতে পারতাম না;) আমার মনে হয় আপনি একবার এটি জিপারের মতো আবিষ্কার করলে এটি বেশ সোজা হয়ে যায় পরে।
কোডিংইশি

যদিও আমি জানতাম যে জিপ এক্সটেনশন পদ্ধতিটি ঠিক কী করে, তবে এটির নাম কেন দেওয়া হয়েছিল তা আমি সবসময়ই আগ্রহী। সফটওয়্যার জিপের সাধারণ জার্গনে সর্বদা অন্যরকম কিছু বোঝানো হয়েছে। দুর্দান্ত উপমা :-) আপনি অবশ্যই স্রষ্টার মন পড়ে থাকতে পারেন।
রঘু রেড্ডি মুত্তানা

7

মন্তব্য বিভাগে পোস্ট করার জন্য আমার কাছে রেপ পয়েন্ট নেই, তবে সম্পর্কিত প্রশ্নের উত্তর দেওয়ার জন্য:

আমি যদি জিপটি চালিয়ে যেতে চাই যেখানে একটি তালিকা উপাদানের বাইরে চলে যায়? যে ক্ষেত্রে সংক্ষিপ্ত তালিকা উপাদানটির ডিফল্ট মান নেওয়া উচিত। এ ক্ষেত্রে আউটপুট এ 1, বি 2, সি 3, ডি 0, ই 0 হবে। - লিয়াং 19 নভেম্বর '15 এ 3:29 এ

আপনি যা করবেন তা হ'ল অ্যারে ব্যবহার করুন। ডিফল্ট মানগুলির সাথে সংক্ষিপ্ত ক্রমটি প্যাড আউট করতে পুনরায় আকার দিন () এবং তারপরে সেগুলি জিপ () করুন।

কোড উদাহরণ:

var letters = new string[] { "A", "B", "C", "D", "E" };
var numbers = new int[] { 1, 2, 3 };
if (numbers.Length < letters.Length)
    Array.Resize(ref numbers, letters.Length);
var q = letters.Zip(numbers, (l, n) => l + n.ToString());
foreach (var s in q)
    Console.WriteLine(s);

আউটপুট:

A1
B2
C3
D0
E0

দয়া করে নোট করুন যে অ্যারে ব্যবহার করে। পুনরায় আকার দিন () এর একটি সতর্কতা রয়েছে : সি # তে রেডিম সংরক্ষণ করুন?

কোন অনুক্রমটি সংক্ষিপ্ততর হবে তা যদি অজানা থাকে তবে একটি ক্রিয়াকলাপ তৈরি করা যেতে পারে যা এটি ঘষে:

static void Main(string[] args)
{
    var letters = new string[] { "A", "B", "C", "D", "E" };
    var numbers = new int[] { 1, 2, 3 };
    var q = letters.Zip(numbers, (l, n) => l + n.ToString()).ToArray();
    var qDef = ZipDefault(letters, numbers);
    Array.Resize(ref q, qDef.Count());
    // Note: using a second .Zip() to show the results side-by-side
    foreach (var s in q.Zip(qDef, (a, b) => string.Format("{0, 2} {1, 2}", a, b)))
        Console.WriteLine(s);
}

static IEnumerable<string> ZipDefault(string[] letters, int[] numbers)
{
    switch (letters.Length.CompareTo(numbers.Length))
    {
        case -1: Array.Resize(ref letters, numbers.Length); break;
        case 0: goto default;
        case 1: Array.Resize(ref numbers, letters.Length); break;
        default: break;
    }
    return letters.Zip(numbers, (l, n) => l + n.ToString()); 
}

জিপডিফল্ট () এর পাশাপাশি প্লেইন। জিপ () এর আউটপুট:

A1 A1
B2 B2
C3 C3
   D0
   E0

মূল প্রশ্ন প্রধান উত্তর ফিরে যাওয়া , অন্য মজার বিষয় যে এক (যখন ক্রম লেন্থ "জিপ করা" বলে আলাদা) করতে ইচ্ছুক পারে তাদের যাতে এমনভাবে যোগদানের হয় শেষ তালিকার টপ এর পরিবর্তে ম্যাচ করে। .Skip () ব্যবহার করে উপযুক্ত সংখ্যক আইটেম "এড়িয়ে" যেতে পারেন।

foreach (var s in letters.Skip(letters.Length - numbers.Length).Zip(numbers, (l, n) => l + n.ToString()).ToArray())
Console.WriteLine(s);

আউটপুট:

C1
D2
E3

আকার পরিবর্তন অপব্যয়, বিশেষত যদি সংগ্রহগুলির মধ্যে দুটি বড় হয়। আপনি যা করতে চান তা হল একটি গণনা যা সংগ্রহ শেষ হওয়ার পরে অব্যাহত থাকে, চাহিদা অনুযায়ী খালি মানগুলি পূরণ করে (ব্যাকিং সংগ্রহ ছাড়াই)। আপনি এটি দিয়ে এটি করতে পারেন: public static IEnumerable<T> Pad<T>(this IEnumerable<T> input, long minLength, T value = default(T)) { long numYielded = 0; foreach (T element in input) { yield return element; ++numYielded; } while (numYielded < minLength) { yield return value; ++numYielded; } }
পেজফল্ট

দেখে মনে হচ্ছে আমি কীভাবে একটি মন্তব্যে সফলভাবে কোড ফর্ম্যাট করব ...
পেজফল্ট

7

এখানে প্রচুর উত্তর প্রদর্শিত হয় Zip, কিন্তু বাস্তব জীবনের ব্যবহারের ক্ষেত্রে ব্যাখ্যা না দিয়ে যা ব্যবহারকে অনুপ্রাণিত করে Zip

একটি বিশেষত সাধারণ প্যাটার্ন যা Zipক্রমাগত জোড়া জিনিস নিয়ে পুনরাবৃত্তি করার জন্য দুর্দান্ত। এটি একটি গণনীয় iterating দ্বারা সম্পন্ন করা হয় Xনিজেই সঙ্গে, 1 উপাদান কুঁদন: x.Zip(x.Skip(1)। ভিজ্যুয়াল উদাহরণ:

 x | x.Skip(1) | x.Zip(x.Skip(1), ...)
---+-----------+----------------------
   |    1      |
 1 |    2      | (1, 2)
 2 |    3      | (2, 1)
 3 |    4      | (3, 2)
 4 |    5      | (4, 3)

এই ধারাবাহিক যুগল মানগুলির মধ্যে প্রথম পার্থক্য সন্ধানের জন্য দরকারী। উদাহরণস্বরূপ, একের পর এক জোড়া IEnumable<MouseXPosition>উত্পাদন করতে ব্যবহার করা যেতে পারে IEnumerable<MouseXDelta>। একইভাবে, boolএর একটি নমুনাযুক্ত মানগুলি / / / এর buttonমতো ইভেন্টগুলিতে ব্যাখ্যা করা যায় । এই ইভেন্টগুলি তখন ডেলিগেট পদ্ধতিতে কল চালাতে পারে। এখানে একটি উদাহরণ:NotPressedClickedHeldReleased

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

enum MouseEvent { NotPressed, Clicked, Held, Released }

public class Program {
    public static void Main() {
        // Example: Sampling the boolean state of a mouse button
        List<bool> mouseStates = new List<bool> { false, false, false, false, true, true, true, false, true, false, false, true };

        mouseStates.Zip(mouseStates.Skip(1), (oldMouseState, newMouseState) => {
            if (oldMouseState) {
                if (newMouseState) return MouseEvent.Held;
                else return MouseEvent.Released;
            } else {
                if (newMouseState) return MouseEvent.Clicked;
                else return MouseEvent.NotPressed;
            }
        })
        .ToList()
        .ForEach(mouseEvent => Console.WriteLine(mouseEvent) );
    }
}

ছাপে:

NotPressesd
NotPressesd
NotPressesd
Clicked
Held
Held
Released
Clicked
Released
NotPressesd
Clicked

6

অন্যরা যেমন বলেছে, জিপ আপনাকে আরও লিনাক স্টেটমেন্টে বা ফোরচ লুপে দুটি সংগ্রহের একত্রিত করতে দেয় lets

লুপ এবং দুটি অ্যারে ব্যবহারের জন্য অপারেশনগুলি এখন কোনও বেনামি অবজেক্ট ব্যবহার করে ফরচ লুপে করা যেতে পারে।

একটি উদাহরণ আমি সবেমাত্র আবিষ্কার করেছি, এটি নিরীহ ধরনের, তবে সমান্তরালকরণ উপকারী হলে পার্শ্বপ্রতিক্রিয়ার সাথে একক লাইনের কাতারে ট্র্যাভারসাল হতে পারে তবে তা কার্যকর হতে পারে:

timeSegments
    .Zip(timeSegments.Skip(1), (Current, Next) => new {Current, Next})
    .Where(zip => zip.Current.EndTime > zip.Next.StartTime)
    .AsParallel()
    .ForAll(zip => zip.Current.EndTime = zip.Next.StartTime);

টাইম বিভাগগুলি একটি সারিতে বর্তমান বা শনাক্ত আইটেমগুলি উপস্থাপন করে (শেষ উপাদানটি জিপ দ্বারা কাটা হয়)। টাইমসেজমেন্টস.স্কিপ (1) পরবর্তী বা পিক আইটেমগুলিকে একটি সারিতে উপস্থাপন করে। জিপ পদ্ধতিটি এই দুটিকে একটি নেক্সট এবং বর্তমান সম্পত্তি সহ একক বেনামে মিশ্রিত করে। তারপরে আমরা যেখানে ফিল্টার করি এবং AsParallel () দিয়ে পরিবর্তন করি For অবশ্যই শেষ বিটটি কেবল নিয়মিত ভবিষ্যদ্বাণী বা অন্য কোনও সিলেক্ট স্টেটমেন্ট হতে পারে যা আপত্তিকর সময় বিভাগগুলি প্রদান করে।


3

জিপ পদ্ধতিটি আপনাকে কলার, আপনার দ্বারা কোনও মার্জিং ফাংশন সরবরাহকারী ব্যবহার করে দুটি সম্পর্কিত নয় এমন ক্রমগুলি "মার্জ" করতে দেয়। এমএসডিএন-এর উদাহরণটি আপনি জিপ দিয়ে কী করতে পারেন তা প্রদর্শনের ক্ষেত্রে আসলে বেশ ভাল। এই উদাহরণস্বরূপ, আপনি দুটি স্বেচ্ছাচারিত, অসম্পৃক্ত সিকোয়েন্স গ্রহণ করেন এবং একটি স্বেচ্ছাসেবী ফাংশন ব্যবহার করে তাদের একত্রিত করুন (এই ক্ষেত্রে কেবলমাত্র উভয় সিকোয়েন্স থেকে আইটেমগুলিকে একক স্ট্রিংয়ের সাথে যুক্ত করে)।

int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };

var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);

foreach (var item in numbersAndWords)
    Console.WriteLine(item);

// This code produces the following output:

// 1 one
// 2 two
// 3 three

0
string[] fname = { "mark", "john", "joseph" };
string[] lname = { "castro", "cruz", "lopez" };

var fullName = fname.Zip(lname, (f, l) => f + " " + l);

foreach (var item in fullName)
{
    Console.WriteLine(item);
}
// The output are

//mark castro..etc
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.