সি # ফোরচ উন্নতি?


9

প্রোগ্রামিংয়ের সময় আমি প্রায়শই এটি চালিয়ে যাই যেখানে আমি একটি পূর্বাভাসের ভিতরে একটি লুপ গণনা সূচক রাখতে চাই এবং একটি পূর্ণসংখ্যা তৈরি করতে পারি, এটি ব্যবহার করতে পারি, বর্ধন করা ইত্যাদি a একটি foreach ভিতরে লুপ গণনা? এটি অন্যান্য লুপগুলিতেও ব্যবহার করা যেতে পারে।

এটি কীওয়ার্ডগুলির ব্যবহারের বিপরীতে যায় কি না দেখে কম্পাইলার কীভাবে এই কীওয়ার্ডটিকে অন্য কোনও লুপ নির্মাণে ব্যবহার করতে দেয় না?


7
আপনি নিজে এটি একটি এক্সটেনশন পদ্ধতিতে করতে পারেন, ড্যান ফিঞ্চের উত্তর দেখুন: stackoverflow.com/a/521894/866172 (সেরা রেট করা উত্তর নয়, তবে আমি মনে করি এটি "ক্লিনার" এক)
জালান

পার্ল এবং stuff _ এর মতো স্টাফ মনে আসে। আমি যে জিনিস ঘৃণা করি।
ইয়াম মার্কোভিচ

2
আমি সি # সম্পর্কে যা জানি তা থেকে এর অনেকগুলি প্রসঙ্গ-ভিত্তিক কীওয়ার্ড রয়েছে, সুতরাং এটি "কীওয়ার্ডগুলির ব্যবহারের বিরুদ্ধে যাবে না"। নীচের উত্তরে যেমন উল্লেখ করা হয়েছে তবে আপনি সম্ভবত একটি for () লুপ ব্যবহার করতে চান ।
ক্রেইজ

@ জালেন দয়া করে উত্তর হিসাবে পোস্ট করুন। এটি সেরা পদ্ধতির এক।
অপুরভ খুরসিয়া

@ মনস্টারট্রাক: আমার মনে হয় না সে উচিত। আসল সমাধানটি হ'ল এই প্রশ্নটি এসও-তে স্থানান্তরিত করা এবং জালেন যে প্রশ্নের সাথে লিঙ্ক করেছেন প্রশ্নের নকল হিসাবে এটি বন্ধ করুন।
ব্রায়ান

উত্তর:


54

আপনার যদি লুপের অভ্যন্তরে একটি লুপ গণনা প্রয়োজন হয় তবে আপনি foreachকেবল নিয়মিত forলুপ ব্যবহার করবেন না কেন । foreachলুপ নির্দিষ্ট ব্যবহারের করতে ইচ্ছে হয়েছিল forসহজ লুপ। দেখে মনে হচ্ছে আপনার এমন পরিস্থিতি রয়েছে যেখানে সরলতা foreachআর উপকারী নয়।


1
+1 - ভাল পয়েন্ট। আইউনামেবল ব্যবহার করার পক্ষে যথেষ্ট সহজ C

11
@ গ্লেনএইচ 7: বাস্তবায়নের উপর নির্ভর করে IEnumerable.Countব্যয়বহুল হতে পারে (বা অসম্ভব, যদি এটি একবারে কেবল গণনা হয়)। নিরাপদে এটি করতে পারার আগে আপনার অন্তর্নিহিত উত্সটি কী তা জানতে হবে।
বাইনারি ওয়ারিয়ার

2
-1: বিল ওয়াগনার আরো কার্যকর C # এর বর্ণনা কেন একজন সবসময় লাগিয়া থাকা উচিত foreachওভার for (int i = 0…)। তিনি কয়েকটি পৃষ্ঠা লিখেছেন তবে আমি দুটি শব্দে সংক্ষেপ করতে পারি - পুনরাবৃত্তির উপর কম্পাইলার অপ্টিমাইজেশন। ঠিক আছে যে দুটি শব্দ ছিল না।
অপুরভ খুরসিয়া

13
@ মুনস্টারট্রাক: বিল ওয়াগনার যা-ই লিখেছেন, আমি ওপি বর্ণিত মত যথেষ্ট পরিস্থিতি দেখেছি, যেখানে একটি forলুপ আরও ভাল পঠনযোগ্য কোড দেয় (এবং তাত্ত্বিক সংকলক অপ্টিমাইজেশন প্রায়শই অকাল অপটিমাইজেশন হয়)।
ডক ব্রাউন

1
@ ডকব্রাউন এটি অকাল অপটিমাইজেশনের মতো সহজ নয়। আমি অতীতে নিজেই বাধাগুলি চিহ্নিত করেছি এবং এই পদ্ধতির সাহায্যে এগুলি ঠিক করেছি (তবে আমি স্বীকার করব যে আমি সংগ্রহের হাজারো জিনিস নিয়ে কাজ করছি)। আশা করি শিগগিরই একটি কাজের উদাহরণ পোস্ট করবেন। এদিকে, এখানে জোন স্কিট । [তিনি বলেছেন পারফরম্যান্সের উন্নতি তাৎপর্যপূর্ণ হবে না তবে এটি সংগ্রহ এবং অবজেক্টের সংখ্যার উপর অনেক বেশি নির্ভর করে]
অপুরভ খুরসিয়া

37

আপনি এর মতো বেনামে ব্যবহার করতে পারেন

foreach (var item in items.Select((v, i) => new { Value = v, Index = i }))
{
    Console.WriteLine("Item value is {0} and index is {1}.", item.Value, item.Index);
}

এটি পাইথনের enumerateফাংশনের অনুরূপ

for i, v in enumerate(items):
    print v, i

+1 ওহ ... হালকা বাল্ব আমি যে পদ্ধতির পছন্দ। কেন আগে আমি এর আগে চিন্তা করিনি?
ফিল

17
লুপের জন্য ক্লাসিকালের চেয়ে যে সি-এ এটি পছন্দ করে তার স্পষ্টতই পঠনযোগ্যতার বিষয়ে এক অদ্ভুত মতামত রয়েছে। এটি একটি ঝরঝরে কৌতুক হতে পারে তবে আমি উত্পাদন মানের কোডের মতো কিছু করতে দেব না। এটি লুপের জন্য ধ্রুপদী তুলনায় অনেক গোলমাল এবং দ্রুত বুঝতে পারে না।
ফ্যালকন

4
@ ফ্যালকন, যদি আপনি লুপের জন্য কোনও পুরানো ফ্যাশন ব্যবহার করতে না পারেন (যার একটি গণনা প্রয়োজন) তবে এটি একটি বৈধ বিকল্প । এটি আমার কাছে প্রায় কাজ করার মতো কয়েকটি অবজেক্টের সংগ্রহ ...
ফ্যাব্রিকিও আরাউজো

8
@ ফ্যাব্রিকিওআরাউজো: লুপের জন্য অবশ্যই সি # এর একটি গণনার প্রয়োজন নেই। যতদূর আমি জানি তারা লুপের জন্য সি এর সমান, যার অর্থ আপনি লুপটি শেষ করতে কোনও বুলিয়ান মান ব্যবহার করতে পারেন। যেমন মুভনেক্সট মিথ্যা ফেরতলে গণনার শেষের জন্য একটি চেক।
ঝ্যান লিংস

1
ফোরচ ব্লক শুরুতে ইনক্রিমেন্টটি সন্ধান করার পরিবর্তে এটি বৃদ্ধির জন্য সমস্ত কোড থাকার অতিরিক্ত যুক্ত সুবিধা রয়েছে।
জেফো

13

অনুরোধ অনুসারে আমি এখানে ড্যান ফিঞ্চের উত্তরটি যুক্ত করছি ।

আমাকে পয়েন্ট দেবেন না, ড্যান ফিঞ্চকে পয়েন্ট দিন :-)

সমাধানটি নিম্নলিখিত জেনেরিক এক্সটেনশন পদ্ধতিটি লিখতে হবে:

public static void Each<T>( this IEnumerable<T> ie, Action<T, int> action )
{
    var i = 0;
    foreach ( var e in ie ) action( e, i++ );
}

যা এর মতো ব্যবহৃত হয়:

var strings = new List<string>();
strings.Each( ( str, n ) =>
{
    // hooray
} );

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

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

আমি মার্ক মুলিনের সাথে একমত, আপনি উভয় পক্ষেই তর্ক করতে পারেন। আমি ভেবেছিলাম এটি এক্সটেনশন পদ্ধতিগুলির একটি দুর্দান্ত চালাক ব্যবহার এবং এটি প্রশ্নটি ফিট করে তাই আমি এটি ভাগ করে নিই।
জালান

5

আমি এই সম্পর্কে ভুল হতে পারি, তবে আমি সর্বদা ভেবেছিলাম যে ফোরচ লুপের মূল পয়েন্টটি ছিল সি ++ এর এসটিএল দিনগুলি থেকে পুনরাবৃত্তি সহজ করা ie

for(std::stltype<typename>::iterator iter = stl_type_instance.begin(); iter != stl_type_instance.end(); iter++)
{
   //dereference iter to use each object.
}

.NET এর পূর্বাভাসে IEnumerable ব্যবহারের সাথে এটি তুলনা করুন

foreach(TypeName instance in DescendentOfIEnumerable)
{
   //use instance to use the object.
}

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


4
+1: খুব কম লোক মনে রাখে যে ফোরচ মূলত আয়রেটর প্যাটার্নের তুলনায় সিনট্যাকটিক চিনি।
স্টিভেন ইভার্স

1
ঠিক আছে কিছু পার্থক্য আছে; পয়েন্টার ম্যানিপুলেশন যেখানে উপস্থিত রয়েছে। নেট নেট প্রোগ্রামার থেকে খুব গভীরভাবে লুকানো আছে, তবে আপনি লুপের জন্য এমন একটি লিখতে পারেন যা দেখতে অনেকটা সি ++ উদাহরণের মতো for(IEnumerator e=collection.GetEnumerator;e.MoveNext();) { ... }
দেখাচ্ছিল

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

* মান প্রকার কাঠামোগত প্রকার নয়। দুঃখিত।
জোনাথন হেনসন

2

যদি প্রশ্নে থাকা সংগ্রহটি একটি হয় তবে IList<T>আপনি কেবল forসূচক সহ ব্যবহার করতে পারেন :

for (int i = 0; i < collection.Count; i++)
{
    var item = collection[i];
    // …
}

যদি তা না হয় তবে আপনি এটি ব্যবহার করতে পারেন Select(), এটির একটি ওভারলোড রয়েছে যা আপনাকে সূচক দেয়।

যদি এটিও উপযুক্ত না হয় তবে আমি মনে করি যে সূচিটি ম্যানুয়ালি বজায় রাখা যথেষ্ট সহজ, এটি কোডের মাত্র দুটি খুব ছোট লাইন lines বিশেষত এর জন্য একটি কীওয়ার্ড তৈরি করা ওভারকিল হবে।

int i = 0;
foreach (var item in collection)
{
    // …
    i++;
}

+1, এছাড়াও, যদি আপনি লুপের অভ্যন্তরে ঠিক একবার সূচক ব্যবহার করেন, আপনি কোন সূচকটি প্রয়োজন তার উপর নির্ভর করে foo(++i)বা কিছু করতে পারেন foo(i++)
চাকরী

2

যদি আপনি সমস্ত কিছু জানেন যে সংগ্রহটি একটি আইনুমেয়রিয়াল তবে আপনার এখন পর্যন্ত কতগুলি উপাদান প্রক্রিয়া করা হয়েছে তার ট্র্যাক রাখা প্রয়োজন (এবং এভাবে আপনি যখন শেষ করেছেন মোট), আপনি লুপের জন্য একটি মৌলিকটিতে কয়েকটি লাইন যুক্ত করতে পারেন:

var coll = GetMyCollectionAsAnIEnumerable();
var idx = 0;
for(var e = coll.GetEnumerator(); e.MoveNext(); idx++)
{
   var elem = e.Current;

   //use elem and idx as you please
}

আপনি পূর্বাংশে বর্ধিত সূচক ভেরিয়েবলটি যুক্ত করতে পারেন:

var i=0;
foreach(var elem in coll)
{
   //do your thing, then...
   i++;
}

আপনি যদি এই চেহারাটি আরও মার্জিত করতে চান, আপনি এই বিবরণটি "আড়াল" করতে দুটি বা একটি এক্সটেনশন পদ্ধতি সংজ্ঞায়িত করতে পারেন:

public static void ForEach<T>(this IEnumerable<T> input, Action<T> action)
{
    foreach(T elem in input)
        action(elem);
}

public static void ForEach<T>(this IEnumerable<T> input, Action<T, int> action)
{
    var idx = 0;
    foreach(T elem in input)
        action(elem, idx++); //post-increment happens after parameter-passing
}

//usage of the index-supporting method
coll.ForEach((e, i)=>Console.WriteLine("Element " + (i+1) + ": " + e.ToString()));


-1

এর জন্য আমি একটি whileলুপ ব্যবহার করি । লুপগুলিও forকাজ করে এবং অনেক লোক এগুলি পছন্দ করে বলে মনে হয় তবে আমি কেবল এমন forকিছু ব্যবহার করতে চাই যাতে নির্দিষ্ট সংখ্যক পুনরাবৃত্তি থাকবে। IEnumerableগুলি রান সময়ে জেনারেট করা হতে পারে, সুতরাং, আমার মনে, whileআরও বুদ্ধিমান। আপনি যদি চান তবে এটিকে একটি অনানুষ্ঠানিক কোডিং গাইডলাইন বলুন।

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