পিএইচপি-তে কীভাবে রিকার্সআইটিএটরেটর কাজ করে?


89

কিভাবে RecursiveIteratorIteratorকাজ করে?

পিএইচপি ম্যানুয়ালটিতে খুব বেশি দলিলযুক্ত বা ব্যাখ্যা করা যায় না। মধ্যে পার্থক্য কি IteratorIteratorএবং RecursiveIteratorIterator?


4
php.net/manual/en/recursiveiteratoriterator.construct.php এ একটি উদাহরণ রয়েছে এবং php.net/manual/en/class.iteratoriterator.php- এ একটি ভূমিকা রয়েছে - আপনি দয়া করে বোঝাতে পারেন যে ঠিক কী বুঝতে সমস্যা হচ্ছে । ম্যানুয়ালটিতে কী সহজে থাকা উচিত যাতে এটি সহজেই উপলব্ধি করা যায়?
গর্ডন

4
আপনি যদি জিজ্ঞাসা করেন কীভাবে RecursiveIteratorIteratorকাজ করে, আপনি কীভাবে IteratorIteratorকাজ করে তা ইতিমধ্যে বুঝতে পেরেছেন ? আমি বলতে চাইছি এটি মূলত একই, কেবলমাত্র দুজনের দ্বারা খাওয়া ইন্টারফেসটি আলাদা। এবং আপনি কয়েকটি উদাহরণে আরও আগ্রহী বা আপনি অন্তর্নিহিত সি কোড প্রয়োগের ভিন্নতা দেখতে চান?
hakre

@Gordon আমি ছিলাম না কিভাবে নিশ্চিত একক foreach লুপ গাছ কাঠামো সব উপাদান, তর্ক করতে নেই
varuog

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

@hakre তারা উভয়ই সত্যই ভিন্ন। IteratorIteratorমানচিত্র Iteratorএবং IteratorAggregateএকটি মধ্যে Iterator, যেখানে REcusiveIteratorIteratorব্যবহার করা হয় recusivly তর্ক করার জন্য একটিRecursiveIterator
আদম

উত্তর:


253

RecursiveIteratorIteratorএকটি কংক্রিট হয় Iteratorবাস্তবায়নে গাছ ট্র্যাভেরসাল । এটি একটি প্রোগ্রামারকে এমন একটি ধারক বস্তু যা RecursiveIteratorইন্টারফেস প্রয়োগ করে , সাধারণ নীতি, প্রকার, শব্দার্থবিজ্ঞান এবং পুনরাবৃত্তকারীগুলির নিদর্শনগুলির জন্য উইকিপিডিয়ায় আইট্রেটরটি দেখতে পায় ables

পার্থক্য ইন IteratorIteratorযা কংক্রিট হয় Iteratorবাস্তবায়নে বস্তুর ট্র্যাভেরসাল রৈখিক অনুক্রমে (এবং ডিফল্টরূপে যে কোন ধরণের গ্রহণ Traversableতার কন্সট্রাকটর মধ্যে), RecursiveIteratorIteratorএকটি ইন সব নোড উপর লুপিং পারবেন আদেশ গাছ অবজেক্টের এবং তার কন্সট্রাকটর একটি লাগে RecursiveIterator

সংক্ষেপে: RecursiveIteratorIteratorআপনি একটি গাছের উপর লুপ IteratorIteratorকরতে পারবেন, আপনাকে একটি তালিকাতে লুপ করতে দেয়। আমি শীঘ্রই নীচে কিছু কোড উদাহরণ সহ এটি দেখান।

প্রযুক্তিগতভাবে এটি কোনও নোডের সমস্ত বাচ্চাকে (যদি থাকে তবে) ট্র্যাভার করে লিনিয়ারिटी ভেঙে কাজ করে। এটি সম্ভব কারণ সংজ্ঞা অনুসারে নোডের সমস্ত শিশু আবার ক RecursiveIterator। টপলেভেল Iteratorতার অভ্যন্তরীণভাবে RecursiveIteratorতাদের গভীরতার দ্বারা বিভিন্নগুলি স্ট্যাক করে এবং Iteratorট্র্যাভারসালের জন্য বর্তমান সক্রিয় সাবটিতে একটি পয়েন্টার রাখে ।

এটি গাছের সমস্ত নোড ঘুরে দেখার অনুমতি দেয়।

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

রিকার্সিভ ট্র্যাভেরসাল জন্য - যদি না আপনি একটি ব্যবহার করবেন না প্রাক সংজ্ঞায়িত Traversalইতিমধ্যে আছে রিকার্সিভ ট্র্যাভেরসাল পুনরাবৃত্তির - আপনি সাধারণত প্রয়োজন বিদ্যমান instantiate করার RecursiveIteratorIteratorপুনরাবৃত্তির বা এমনকি লিখতে একটি recursive ট্র্যাভেরসাল পুনরাবৃত্তির একটি যে Traversableট্র্যাভেরসাল পুনরাবৃত্তির সঙ্গে এই ধরনের আছে আপনার নিজের foreach

টিপ: আপনি সম্ভবত একটি বা অন্যটিকে নিজের রূপায়িত করেননি, সুতরাং তাদের পার্থক্য সম্পর্কে আপনার ব্যবহারিক অভিজ্ঞতার জন্য এটি করার মতো কিছু হতে পারে। উত্তরের শেষে আপনি একটি ডিআইওয়াই পরামর্শ পান।

সংক্ষেপে প্রযুক্তিগত পার্থক্য:

  • যদিও IteratorIteratorকোনো লাগে Traversableরৈখিক ট্র্যাভেরসাল জন্য, RecursiveIteratorIteratorআরো একটি নির্দিষ্ট চাহিদা RecursiveIteratorএকটি গাছ উপর লুপ।
  • যেখানে IteratorIteratorএটির Iteratorমাধ্যমে এর প্রধানটিকে উন্মোচিত করে getInnerIerator(), কেবলমাত্র সেই পদ্ধতির মাধ্যমে RecursiveIteratorIteratorবর্তমান সক্রিয় উপ-সরবরাহ করে Iterator
  • যদিও IteratorIteratorসম্পূর্ণভাবে নয় পিতা বা মাতা বা শিশু মত কিছু সচেতন, RecursiveIteratorIteratorপেতে এবং ঢুকা শিশুদের কিভাবে পাশাপাশি জানেন।
  • IteratorIteratorপুনরুক্তিকারীদের একটি স্ট্যাকের প্রয়োজন নেই, RecursiveIteratorIteratorএ জাতীয় স্ট্যাক রয়েছে এবং সক্রিয় উপ-পুনরুক্তিকারীকে জানেন।
  • IteratorIteratorরৈখিকতার কারণে এবং তার কোনও পছন্দ না হওয়ার কারণে এর অর্ডার যেখানে রয়েছে, সেখানে RecursiveIteratorIteratorআরও ট্র্যাভারসাল করার জন্য একটি পছন্দ রয়েছে এবং প্রতিটি নোড ( প্রতি মোডেরRecursiveIteratorIterator মাধ্যমে সিদ্ধান্ত নেওয়া ) অনুযায়ী সিদ্ধান্ত নেওয়া দরকার ।
  • RecursiveIteratorIteratorএর চেয়েও বেশি পদ্ধতি রয়েছে IteratorIterator

সংক্ষিপ্তসার হিসাবে: RecursiveIteratorএকটি কংক্রিট ধরণের পুনরাবৃত্তি (একটি গাছের উপরে লুপিং) যা তার নিজস্ব পুনরাবৃত্তির উপর কাজ করে, যথা RecursiveIterator। এটি যেমন একই অন্তর্নিহিত নীতি IteratorIerator, তবে পুনরাবৃত্তির ধরণটি আলাদা (লিনিয়ার ক্রম)।

আদর্শভাবে আপনি নিজের সেটও তৈরি করতে পারেন। শুধুমাত্র প্রয়োজনীয় জিনিস যে আপনার পুনরুক্তিকারীর কার্যকরী Traversableযা মাধ্যমে সম্ভব Iteratorবা IteratorAggregate। তারপরে আপনি এটি ব্যবহার করতে পারেন foreach। উদাহরণস্বরূপ ধারক বস্তুর (গুলি) জন্য নির্দিষ্ট পুনরাবৃত্ত ইন্টারফেসের সাথে এক ধরণের টেরিনারি ট্রি ট্রভারসাল পুনরাবৃত্তি পুনরাবৃত্তি অবজেক্ট।


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

উদাহরণস্বরূপ একটি ডিরেক্টরি তালিকা নিন। আপনি ডিস্কে নিম্নলিখিত ফাইল এবং ডিরেক্টরি ট্রি পেয়েছেন বিবেচনা করুন:

ডিরেক্টরি ট্রি

লিনিয়ার অর্ডার সহ একটি পুনরাবৃত্তি কেবল শীর্ষ স্তরের ফোল্ডার এবং ফাইলগুলি (একটি একক ডিরেক্টরি তালিকা) এর উপর দিয়ে গেলেও পুনরাবৃত্ত পুনরাবৃত্তকারী সাবফোল্ডারগুলির মাধ্যমেও ট্র্যাভ করে এবং সমস্ত ফোল্ডার এবং ফাইল তালিকাভুক্ত করে (যার ডিরেক্টরিগুলি তার উপ-ডিরেক্টরিগুলির তালিকা সহ তালিকাভুক্ত করে):

Non-Recursive        Recursive
=============        =========

   [tree]            [tree]
    ├ dirA            ├ dirA
    └ fileA           │ ├ dirB
                      │ │ └ fileD
                      │ ├ fileB
                      │ └ fileC
                      └ fileA

আপনি IteratorIteratorএটির সাথে সহজেই তুলনা করতে পারেন যার সাথে ডিরেক্টরিতে ডিরেক্টরি ট্রি অনুসরণ করার জন্য কোনও পুনরাবৃত্তি ঘটে না। এবং RecursiveIteratorIteratorযা গাছটিতে পুনরাবৃত্তির তালিকার শো হিসাবে প্রবেশ করতে পারে।

একটি প্রথম একটি খুব মৌলিক উদাহরণ DirectoryIteratorযে কার্যকরী Traversableযা করতে পারবেন foreachকরার বারবার এটি উপর:

$path = 'tree';
$dir  = new DirectoryIterator($path);

echo "[$path]\n";
foreach ($dir as $file) {
    echo " ├ $file\n";
}

উপরের ডিরেক্টরি কাঠামোর জন্য অনুকরণীয় আউটপুট হ'ল:

[tree]
 ├ .
 ├ ..
 ├ dirA
 ├ fileA

আপনি দেখতে হিসাবে এটি এখনও ব্যবহার করে না IteratorIteratorবা RecursiveIteratorIterator। পরিবর্তে এটি কেবল ইন্টারফেসে foreachচালিত ব্যবহার করে Traversable

হিসাবে foreachডিফল্টভাবে কেবল রৈখিক অর্ডার নামে পুনরাবৃত্তির ধরণ জানে, আমরা স্পষ্টভাবে পুনরাবৃত্তির প্রকার চাইবেন। প্রথম নজরে এটি খুব ভার্জোজ মনে হতে পারে, তবে প্রদর্শনের উদ্দেশ্যে (এবং RecursiveIteratorIteratorপরে আরও দৃশ্যমানের সাথে পার্থক্য তৈরি করার জন্য ), পুনরাবৃত্তির রৈখিক প্রকারটি নির্দিষ্ট IteratorIteratorকরে ডিরেক্টরি তালিকাতে পুনরাবৃত্তির ধরণটি স্পষ্টভাবে নির্দিষ্ট করে দিন :

$files = new IteratorIterator($dir);

echo "[$path]\n";
foreach ($files as $file) {
    echo " ├ $file\n";
}

এই উদাহরণটি প্রথমটির সাথে প্রায় একই রকম, পার্থক্যটি $filesহ'ল এখন এক IteratorIteratorধরণের পুনরাবৃত্তি Traversable $dir:

$files = new IteratorIterator($dir);

যথারীতি পুনরাবৃত্তির কাজটি সম্পাদন করে foreach:

foreach ($files as $file) {

আউটপুট ঠিক একই। তাহলে আলাদা কি? এর মধ্যে ব্যবহৃত বস্তুটি ভিন্ন foreach। প্রথম উদাহরণে এটি একটি হল DirectoryIteratorদ্বিতীয় উদাহরণে এটা IteratorIterator। এটি দেখায় নমনীয়তা পুনরাবৃত্তিকারীদের: আপনি একে অপরের সাথে প্রতিস্থাপন করতে পারেন, অভ্যন্তরীণ কোডটি foreachকেবল প্রত্যাশা অনুযায়ী কাজ চালিয়ে যেতে পারে।

সাব ডিরেক্টরিগুলি সহ পুরো তালিকা পেতে শুরু করুন।

যেহেতু আমরা এখন পুনরাবৃত্তির ধরণ উল্লেখ করেছি, আসুন এটি অন্য ধরণের পুনরাবৃত্তিতে পরিবর্তন করতে বিবেচনা করুন।

আমরা জানি আমাদের প্রথম গাছটি কেবল প্রথম স্তরের নয়, এখনই পুরো গাছটি অতিক্রম করতে হবে। একটি সহজ সঙ্গে যে কাজ আছে করার foreachআমরা পুনরুক্তিকারীর নিয়ে বিভিন্ন ধরনের প্রয়োজন: RecursiveIteratorIterator। এবং যেটি কেবলমাত্র সেই কনটেইনার বস্তুগুলির মধ্যে পুনরাবৃত্তি করতে পারে যার RecursiveIteratorইন্টারফেস রয়েছে

ইন্টারফেসটি একটি চুক্তি। এটি প্রয়োগকারী যে কোনও শ্রেণীর সাথে একসাথে ব্যবহার করা যেতে পারে RecursiveIteratorIterator। এই জাতীয় শ্রেণীর উদাহরণ হ'ল RecursiveDirectoryIterator, যা এর পুনরাবৃত্ত রূপের মতো DirectoryIterator

আই-শব্দের সাথে অন্য কোনও বাক্য লেখার আগে একটি প্রথম কোড উদাহরণ দেখতে দিন:

$dir  = new RecursiveDirectoryIterator($path);

echo "[$path]\n";
foreach ($dir as $file) {
    echo " ├ $file\n";
}

এই তৃতীয় উদাহরণটি প্রথমটির সাথে প্রায় একই রকম, তবে এটি কিছু আলাদা আউটপুট তৈরি করে:

[tree]
 ├ tree\.
 ├ tree\..
 ├ tree\dirA
 ├ tree\fileA

ঠিক আছে, এর চেয়ে আলাদা নয়, ফাইলের নামটিতে এখন সামনের পথের নামটি রয়েছে, তবে বাকিগুলিও একইরকম দেখাচ্ছে।

যেমন উদাহরণটি দেখায়, এমনকি ডিরেক্টরি অবজেক্টটি ইতিমধ্যে RecursiveIteratorইন্টারফেসকে পরিপূরণ করে , foreachএটি পুরো ডিরেক্টরি ট্রিটিকে অতিক্রম করতে যথেষ্ট নয় । এখানেই কার্যকর হয় RecursiveIteratorIteratorউদাহরণ 4 দেখায় কিভাবে:

$files = new RecursiveIteratorIterator($dir);

echo "[$path]\n";
foreach ($files as $file) {
    echo " ├ $file\n";
}

RecursiveIteratorIteratorকেবল পূর্ববর্তী $dirঅবজেক্টের পরিবর্তে ব্যবহার foreachকরা সমস্ত ফাইল এবং ডিরেক্টরিকে পুনরাবৃত্ত পদ্ধতিতে অতিক্রম করবে । এটি তখন সমস্ত ফাইল তালিকাভুক্ত করে, কারণ বস্তুর পুনরাবৃত্তির ধরণটি এখন নির্দিষ্ট করা হয়েছে:

[tree]
 ├ tree\.
 ├ tree\..
 ├ tree\dirA\.
 ├ tree\dirA\..
 ├ tree\dirA\dirB\.
 ├ tree\dirA\dirB\..
 ├ tree\dirA\dirB\fileD
 ├ tree\dirA\fileB
 ├ tree\dirA\fileC
 ├ tree\fileA

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

echo "[$path]\n";
foreach ($files as $file) {
    $indent = str_repeat('   ', $files->getDepth());
    echo $indent, " ├ $file\n";
}

এবং উদাহরণ 5 এর আউটপুট :

[tree]
 ├ tree\.
 ├ tree\..
    ├ tree\dirA\.
    ├ tree\dirA\..
       ├ tree\dirA\dirB\.
       ├ tree\dirA\dirB\..
       ├ tree\dirA\dirB\fileD
    ├ tree\dirA\fileB
    ├ tree\dirA\fileC
 ├ tree\fileA

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

মেটা-তথ্যের অনুরূপ, গাছকে কীভাবে অতিক্রম করতে হবে এবং এর ফলে আউটপুট অর্ডার করার বিভিন্ন উপায়ও রয়েছে। এই মোড এরRecursiveIteratorIterator এবং এটি কন্সট্রাকটর সঙ্গে নির্ধারণ করা যাবে।

পরবর্তী উদাহরণটি RecursiveDirectoryIteratorডট এন্ট্রিগুলি ( .এবং ..) অপসারণ করতে বলবে কারণ আমাদের প্রয়োজন নেই them তবে পুনরাবৃত্তি মোডটি SELF_FIRSTবাচ্চাদের আগে (সাব-ডিরেক্টরীতে ফাইল এবং সাব-সাবডিয়ার্স ) প্রথমে প্যারেন্ট এলিমেন্টকে (সাব-ডাইরেক্টরি) নিতে নেওয়া হবে :

$dir  = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);

echo "[$path]\n";
foreach ($files as $file) {
    $indent = str_repeat('   ', $files->getDepth());
    echo $indent, " ├ $file\n";
}

আউটপুট এখন সাবডিরেক্টরি এন্ট্রিগুলি সঠিকভাবে তালিকাভুক্ত দেখায়, আপনি যদি পূর্ববর্তী আউটপুটটি সেখানে উপস্থিত না থেকে তুলনা করেন:

[tree]
 ├ tree\dirA
    ├ tree\dirA\dirB
       ├ tree\dirA\dirB\fileD
    ├ tree\dirA\fileB
    ├ tree\dirA\fileC
 ├ tree\fileA

পুনরাবৃত্তি মোড তাই এবং কখন গাছের একটি ব্রাচ বা পাতা ফিরে আসে তা নিয়ন্ত্রণ করে, উদাহরণস্বরূপ ডিরেক্টরি উদাহরণের জন্য:

  • LEAVES_ONLY (ডিফল্ট): কেবল ফাইলগুলি তালিকাবদ্ধ করুন, কোনও ডিরেক্টরি নেই।
  • SELF_FIRST (উপরে): তালিকা ডিরেক্টরি এবং তারপরে সেখানে ফাইলগুলি।
  • CHILD_FIRST (ডাব্লু / ও উদাহরণ): প্রথমে সাব-ডিরেক্টরিতে ফাইল তালিকাভুক্ত করুন, তারপরে ডিরেক্টরিটি।

অন্য দুটি মোডের সাথে উদাহরণ 5 এর আউটপুট :

  LEAVES_ONLY                           CHILD_FIRST

  [tree]                                [tree]
         ├ tree\dirA\dirB\fileD                ├ tree\dirA\dirB\fileD
      ├ tree\dirA\fileB                     ├ tree\dirA\dirB
      ├ tree\dirA\fileC                     ├ tree\dirA\fileB
   ├ tree\fileA                             ├ tree\dirA\fileC
                                        ├ tree\dirA
                                        ├ tree\fileA

আপনি যখন এটি স্ট্যান্ডার্ড ট্র্যাভারসাল সাথে তুলনা করেন, এই সমস্ত জিনিস উপলব্ধ হয় না। পুনরাবৃত্তির পুনরাবৃত্তির ফলে আপনার মাথাটি যখন আপনার চারপাশে মুড়ে ফেলার দরকার হয় তখন এটি আরও জটিল হয় তবে এটি ব্যবহার করা সহজ কারণ এটি কেবল একটি পুনরুক্তির মতো আচরণ করে, আপনি এটি একটিতে রেখে দিয়ে গিয়েছেন foreach

আমি মনে করি এগুলি একটি উত্তরের জন্য যথেষ্ট উদাহরণ। আপনি পুরো উত্স-কোডের পাশাপাশি এই গিস্টটিতে সুন্দর চেহারার অ্যাস্কি-গাছগুলি প্রদর্শন করার জন্য একটি উদাহরণ পেতে পারেন: https://gist.github.com/3599532

এটি নিজেই করুন:RecursiveTreeIterator লাইন দিয়ে কাজের লাইন তৈরি করুন ।

5 উদাহরণ উদাহরণস্বরূপ প্রমাণ করেছে যে পুনরাবৃত্তকারীদের রাষ্ট্রের সম্পর্কে মেটা-তথ্য রয়েছে। যাইহোক, এই উদ্দেশ্যপূর্ণ প্রদর্শিত হয়েছে মধ্যেforeach পুনরাবৃত্তির। বাস্তব জীবনের এই স্বাভাবিকভাবেই ভিতরে জন্যে RecursiveIterator

এর চেয়ে ভাল উদাহরণ হ'ল RecursiveTreeIterator, এটি ইনডেন্টিং, প্রিফিক্সিং ইত্যাদির যত্ন নেয়। নিম্নলিখিত কোড টুকরা দেখুন:

$dir   = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$lines = new RecursiveTreeIterator($dir);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));

RecursiveTreeIteratorলাইন দ্বারা কাজ লাইন দেয়ার উদ্দেশ্যে করা হচ্ছে, আউটপুট চমত্কার সোজা এক সামান্য সমস্যা নিয়ে এগিয়ে হল:

[tree]
 ├ tree\dirA
 │ ├ tree\dirA\dirB
 │ │ └ tree\dirA\dirB\fileD
 │ ├ tree\dirA\fileB
 │ └ tree\dirA\fileC
 └ tree\fileA

RecursiveDirectoryIteratorএটির সাথে সংমিশ্রণে ব্যবহার করার সময় এটি কেবলমাত্র ফাইলের নামটিই নয় পুরো পথটি প্রদর্শন করে। বাকিটা দেখতে ভাল লাগছে। কারণ ফাইল-নামগুলি উত্পন্ন হয় SplFileInfo। সেগুলি পরিবর্তে বেসনাম হিসাবে প্রদর্শিত হবে। পছন্দসই আউটপুট নিম্নলিখিত:

/// Solved ///

[tree]
 ├ dirA
 │ ├ dirB
 │ │ └ fileD
 │ ├ fileB
 │ └ fileC
 └ fileA

একটি ডেকোরেটার ক্লাস তৈরি করুন যা এর RecursiveTreeIteratorপরিবর্তে ব্যবহার করা যেতে পারে RecursiveDirectoryIterator। এটি পথের SplFileInfoপরিবর্তে বর্তমানের বেসনামটি সরবরাহ করতে হবে। চূড়ান্ত কোড খণ্ডটি এর পরে দেখতে পেল:

$lines = new RecursiveTreeIterator(
    new DiyRecursiveDecorator($dir)
);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));

এই টুকরোগুলি সহ পরিশিষ্টের$unicodeTreePrefix সংক্ষেপের অংশ : এটি নিজে করুন: RecursiveTreeIteratorলাইনের সাহায্যে ওয়ার্ক লাইন করুন ।


আপনি যখন পুনরাবৃত্তিটি কাস্টমাইজ করতে চলেছেন তখন এটি উত্থাপিত প্রশ্নের উত্তর দেয় না, প্রকৃত ত্রুটিগুলি এবং মূল পয়েন্টগুলি মিস করে। সব মিলিয়ে দেখে মনে হচ্ছে যে কোনও বিষয়ে অনুদান পাওয়ার জন্য এটি একটি দুর্বল প্রয়াস, যা সম্পর্কে আপনি খুব বেশি জানেন না বা যদি আপনি করেন তবে উত্থাপিত প্রশ্নের উত্তর খুঁজে বের করতে পারবেন না।
সালাতে

4
ভাল যা আমার "কেন" প্রশ্নের উত্তর দেয় না, আপনি কেবল বেশি কিছু না বলে আরও শব্দ তৈরি করেন। হতে পারে আপনি আসলে একটি ত্রুটি যা গণনা করেছেন তা দিয়ে শুরু করবেন? এটিকে নির্দেশ করুন, এটি আপনার গোপন রাখবেন না।
hakre

প্রথম বাক্যটি ভুল: "রিক্সারসিভআইট্রেটিইটরেটর একটি IteratorIterator যা সমর্থন করে ...", এটি সত্য নয়।
সালাতে

4
@ সালাথে: আপনার মতামতের জন্য আপনাকে ধন্যবাদ আমি উত্তরটি সম্পাদন করেছি এটি ঠিকানা। প্রথম বাক্যটি সত্যই ভুল এবং অসম্পূর্ণ ছিল। আমি এখনও কংক্রিট বাস্তবায়নের বিশদটি RecursiveIteratorIteratorএড়িয়ে গেছি কারণ এটি অন্যান্য ধরণের সাথে সাধারণ তবে এটি কীভাবে কাজ করে তা সম্পর্কে আমি কিছু প্রযুক্তিগত ইনফোস দিয়েছিলাম। আমি যে উদাহরণগুলি মনে করি তা পার্থক্যগুলি ভালভাবে দেখায়: পুনরাবৃত্তির ধরণ হ'ল উভয়ের মধ্যে প্রধান পার্থক্য। আপনি যদি পুনরাবৃত্তির ধরণটি কিছুটা আলাদাভাবে মুদ্রা করেন তবে কোনও ধারণা নেই তবে শব্দার্থবিজ্ঞানের ধরণের পুনরাবৃত্তির সাথে আইএমএইচও সহজ নয়।
hakre

4
প্রথম অংশটি কিছুটা উন্নত হয়েছে, তবে একবার আপনি উদাহরণগুলিতে সরে যেতে শুরু করলে এটি তত্ক্ষণাত অপূর্ণতার দিকে ঝুঁকে পড়ে। আপনি যদি অনুভূমিক নিয়মে উত্তরটি ক্রপ করেন তবে এটি অনেক উন্নত হবে।
সালাতে

32

এর পার্থক্য কী IteratorIteratorএবং RecursiveIteratorIterator?

এই দুটি পুনরাবৃত্তির মধ্যে পার্থক্য বুঝতে, প্রথমে ব্যবহৃত নামকরণ কনভেনশনগুলি এবং "পুনরাবৃত্ত" পুনরাবৃত্তকারী বলতে আমরা কী বোঝাতে চাইছি তার সম্পর্কে প্রথমে কিছুটা বুঝতে হবে।

পুনরাবৃত্ত এবং অ-পুনরাবৃত্তি পুনরাবৃত্তি

পিএইচপি-তে অ-পুনরুক্তিযুক্ত পুনরুক্তি রয়েছে, যেমন ArrayIteratorএবংFilesystemIterator । এছাড়াও "পুনরাবৃত্ত" পুনরুক্তি রয়েছে যেমন RecursiveArrayIteratorএবং RecursiveDirectoryIterator। পরেরগুলিতে এমন পদ্ধতি রয়েছে যেগুলি এগুলিকে ড্রিল করতে সক্ষম করে, আগেরটি তা করে না।

এই পুনরাবৃত্তকারীগুলির উদাহরণগুলি যখন তাদের নিজস্বভাবে লুপ করা হয়, এমনকি পুনরাবৃত্তকারীগুলিও, মানগুলি কেবল "শীর্ষ" স্তর থেকে আসে এমনকি সাব-ডিরেক্টরি সহ নেস্টেড অ্যারে বা ডিরেক্টরিতে লুপ করা হলেও।

পুনরাবৃত্তির পুনরাবৃত্তকারীরা পুনরাবৃত্ত আচরণ (মাধ্যমে , ) প্রয়োগ করে তবে শোষণ করে নাhasChildren()getChildren() এটি না।

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

পুনরাবৃত্তিবোধক

এখানেই RecursiveIteratorIteratorখেলতে আসে। এটি "পুনরাবৃত্তযোগ্য" পুনরাবৃত্তিকে এমনভাবে কল করতে পারে যাতে কোনও কাঠামোর মধ্যে কোনও সাধারণ, ফ্ল্যাট, লুপে ড্রিল করতে হয়। এটি পুনরাবৃত্ত আচরণকে ক্রিয়ায় ফেলেছে। এটি মূলত পুনরাবৃত্তির প্রতিটি মানগুলিতে পদক্ষেপ নেওয়ার কাজটি দেখায়, "বাচ্চাদের" পুনরাবৃত্তি করার জন্য "বাচ্চারা" আছে কিনা তা দেখার চেষ্টা করে এবং সেই সমস্ত বাচ্চাদের সংগ্রহের মধ্যে এবং বাইরে বেরিয়ে আসার কাজটি করে। আপনি কোনও ভবিষ্যতের নজির আটকে RecursiveIteratorIteratorরেখেছেন এবং এটি কাঠামোর মধ্যে ডুব দেয় যাতে আপনার দরকার নেই।

যদি RecursiveIteratorIteratorব্যবহার করা হয়নি, আপনি রিকার্সিভ আচরণ কাজে লাগান আপনার নিজস্ব রিকার্সিভ লুপ লিখতে হবে "recursible" পুনরুক্তিকারীর এর বিরুদ্ধে চেক hasChildren()এবং ব্যবহার getChildren()

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

IteratorIterator

এর কাজটি IteratorIteratorহ'ল যে কোনও Traversableবস্তু গ্রহণ করা এবং এটি এমনভাবে মোড়ানো হয় যা এটি Iteratorইন্টারফেসটিকে সন্তুষ্ট করে । এর জন্য একটি ব্যবহার তারপরে অ-পুনরাবৃত্তকারী অবজেক্টে পুনরাবৃত্ত-নির্দিষ্ট আচরণ প্রয়োগ করতে সক্ষম হবেন।

ব্যবহারিক উদাহরণ দেওয়ার জন্য, DatePeriodক্লাসটি Traversableকিন্তু একটি নয় Iterator। এর মতো, আমরা এর মানগুলি লুপ foreach()করতে পারি তবে সাধারণভাবে কোনও পুনরুক্তিকারীর সাথে ফিল্টারিংয়ের মতো অন্যান্য জিনিসগুলি আমরা করতে পারি না।

টাস্ক : আগামী চার সপ্তাহের সোমবার, বুধবার ও শুক্রবারে লুপ।

হ্যাঁ, এই দ্বারা তুচ্ছ হয় foreachওভার -ing DatePeriodএবং ব্যবহার if()লুপ মধ্যে; কিন্তু এটি এই উদাহরণের বিন্দু নয়!

$period = new DatePeriod(new DateTime, new DateInterval('P1D'), 28);
$dates  = new CallbackFilterIterator($period, function ($date) {
    return in_array($date->format('l'), array('Monday', 'Wednesday', 'Friday'));
});
foreach ($dates as $date) { … }

উপরের স্নিপেটটি কাজ করবে না কারণ ইন্টারফেসটি CallbackFilterIteratorকার্যকর করে এমন কোনও শ্রেণীর উদাহরণের প্রত্যাশা করে Iterator, যা DatePeriodনা। তবে এটি যেহেতু Traversableআমরা সহজেই ব্যবহার করে সেই প্রয়োজনীয়তাটি পূরণ করতে পারি IteratorIterator

$period = new IteratorIterator(new DatePeriod(…));

যেমন আপনি দেখতে পাচ্ছেন, এটির পুনরাবৃত্তিকারী ক্লাস বা পুনরাবৃত্তিগুলির সাথে পুনরাবৃত্তি করার কিছুই করার নেই এবং এর মধ্যে IteratorIteratorএবং এর মধ্যে পার্থক্য রয়েছে RecursiveIteratorIterator

সারসংক্ষেপ

RecursiveIteraratorIteratorএকটি RecursiveIterator("পুনরাবৃত্তযোগ্য" পুনরুক্তিযোগ্য) এর মাধ্যমে পুনরাবৃত্তি করার জন্য, উপলব্ধ যে পুনরাবৃত্তির আচরণ ব্যবহার করে।

IteratorIteratorIteratorঅ-পুনরুক্তকারী, Traversableবস্তুগুলিতে আচরণ প্রয়োগের জন্য ।


নয় IteratorIteratorঠিক রৈখিক অর্ডার ট্র্যাভেরসাল মান টাইপ Traversableবস্তু? যা এগুলি ছাড়া এটি ব্যবহার করা যেতে পারে ঠিক foreachতেমন? আর এমনকি আরও, না একটি হয় RecursiveIterator সবসময় একটি Traversableএবং সেইজন্য না শুধুমাত্র IteratorIteratorকিন্তু RecursiveIteratorIteratorসবসময় "আবেদন করার জন্য Iteratorঅ পুনরুক্তিকারীর, Traversable বস্তু ব্যবহার" ? (আমি এখন বলতে চাই foreachযে ধারক বস্তুর মাধ্যমে পুনরাবৃত্তির বস্তুর মাধ্যমে পুনরাবৃত্তির ধরণের প্রয়োগ করা হয় যা কোনও পুনরাবৃত্ত-ধরণের ইন্টারফেস প্রয়োগ করে তাই এগুলি সর্বদা Traversable
পুনরাবৃত্তকারী

আমার উত্তর যেমনটি বলেছে, IteratorIteratorএটি এমন একটি শ্রেণি যা সমস্ত কিছুগুলিতে মোড়কে Traversableরাখা Iteratorএর চেয়ে বেশি কিছু নেই । আপনি এই শব্দটি আরও সাধারণভাবে প্রয়োগ করছেন বলে মনে হচ্ছে।
সালাতে

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

@ সালাথ, আপনি কি জানেন যে পুনরাবৃত্ত পুনরাবৃত্তকারী (রিকার্সডাইরেক্টরিআইট্রেটার) কেন চিলড্রেন (), getChildren () আচরণ প্রয়োগ করে না?
anru

8
"পুনরাবৃত্তিযোগ্য" বলার জন্য +1। নাম একটি দীর্ঘ সময়ের জন্য বিপথে আমার নেতৃত্ব কারণ Recursiveমধ্যে RecursiveIterator, ব্যবহার বোঝা যেহেতু আরও উপযুক্ত নাম এক যা সামর্থ্য বর্ণনা করে, মত হত RecursibleIterator
ছাগল 21

0

এর সাথে ব্যবহার করা হলে iterator_to_array(), RecursiveIteratorIteratorসমস্ত মান সন্ধান করতে পুনরাবৃত্তভাবে অ্যারে চলবে। এর অর্থ এটি আসল অ্যারে সমতল করবে।

IteratorIterator মূল শ্রেণিবদ্ধ কাঠামো রাখবে।

এই উদাহরণটি আপনাকে পরিষ্কারভাবে পার্থক্য দেখাবে:

$array = array(
               'ford',
               'model' => 'F150',
               'color' => 'blue', 
               'options' => array('radio' => 'satellite')
               );

$recursiveIterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
var_dump(iterator_to_array($recursiveIterator, true));

$iterator = new IteratorIterator(new ArrayIterator($array));
var_dump(iterator_to_array($iterator,true));

এটি সম্পূর্ণ বিভ্রান্তিকর। new IteratorIterator(new ArrayIterator($array))এর সমতুল্য new ArrayIterator($array), বাহ্যিক IteratorIteratorকিছুই করছে না। তদুপরি, আউটপুট সমতলকরণের কোনও সম্পর্ক নেই iterator_to_array- এটি কেবল পুনরাবৃত্তিকে অ্যারেতে রূপান্তর করে। সমতলকরণ RecursiveArrayIteratorতার অভ্যন্তর পুনরাবৃত্তির পথে চলার একটি বৈশিষ্ট্য ।
কোলোনেল প্রশ্ন

0

পুনরাবৃত্তির ডিরেক্টরি নির্দেশক এটি পুরো ফাইলের নামটি প্রদর্শন করে কেবল ফাইলের নামই না। বাকিটা দেখতে ভাল লাগছে। কারণ ফাইল-নামগুলি স্প্লফিলআইএনফো দ্বারা উত্পাদিত হয়েছিল। সেগুলি পরিবর্তে বেসনাম হিসাবে প্রদর্শিত হবে। পছন্দসই আউটপুট নিম্নলিখিত:

$path =__DIR__;
$dir = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir,RecursiveIteratorIterator::SELF_FIRST);
while ($files->valid()) {
    $file = $files->current();
    $filename = $file->getFilename();
    $deep = $files->getDepth();
    $indent = str_repeat('│ ', $deep);
    $files->next();
    $valid = $files->valid();
    if ($valid and ($files->getDepth() - 1 == $deep or $files->getDepth() == $deep)) {
        echo $indent, "├ $filename\n";
    } else {
        echo $indent, "└ $filename\n";
    }
}

আউটপুট:

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