Yineleyici - Iterator

İçinde bilgisayar Programlama, bir yineleyici bir nesne bu, bir programcının bir konteyner, özellikle listeler.[1][2][3] Çeşitli yineleyiciler genellikle bir konteyner aracılığıyla sağlanır arayüz. Belirli bir yineleyicinin arayüzü ve anlambilimi sabit olsa da, yineleyiciler genellikle bir kap uygulamasının temelini oluşturan yapılar açısından uygulanır ve yineleyicinin operasyonel anlamını sağlamak için genellikle kaba sıkı bir şekilde bağlanır. Bir yineleyici geçişi gerçekleştirir ve ayrıca bir kaptaki veri öğelerine erişim sağlar, ancak kendi başına çalışmaz yineleme (yani, bu kavramla veya terminolojinin önemsiz kullanımıyla alınan önemli bir özgürlük olmadan)[kaynak belirtilmeli ]. Bir yineleyici davranışsal olarak bir veritabanı imleci. Yineleyiciler, CLU 1974'te programlama dili.

Açıklama

Dahili Yineleyiciler

Dahili yineleyiciler yüksek dereceli fonksiyonlar (sıklıkla alarak anonim işlevler ) gibi harita, azaltmak vb., bir konteyner boyunca geçişi uygulamak, verilen işlevi sırayla her öğeye uygulamak.

Dış yineleyiciler ve yineleyici modeli

Harici bir yineleyici, bir tür Işaretçi iki birincil işlemi olan: nesne koleksiyonundaki belirli bir öğeye başvurma ( eleman erişimi) ve bir sonraki öğeyi işaret edecek şekilde kendini değiştirerek ( eleman geçişi).[4] Ayrıca bir yineleyici oluşturmanın bir yolu olmalı, böylece ilk öğeye işaret etmeli ve yineleyicinin kaptaki tüm öğeleri ne zaman tükettiğini belirlemenin bir yolu olmalıdır. Dile ve kullanım amacına bağlı olarak, yineleyiciler ayrıca ek işlemler sağlayabilir veya farklı davranışlar sergileyebilir.

Bir yineleyicinin birincil amacı, kullanıcıyı kabın iç yapısından izole ederken, bir kullanıcının bir kabın her öğesini işlemesine izin vermektir.[2] Bu, konteynerin öğeleri istediği herhangi bir şekilde depolamasına izin verirken, kullanıcının bunu basit bir sıra veya liste gibi ele almasına izin verir. Yineleyici sınıfı, genellikle karşılık gelen konteyner sınıfıyla sıkı bir koordinasyon içinde tasarlanır. Konteyner genellikle yineleyiciler oluşturmak için yöntemler sağlar.

Bir döngü sayacı bazen döngü yineleyici olarak da adlandırılır. Bir döngü sayacı ancak, yalnızca geçiş işlevselliğini sağlar, öğe erişim işlevselliğini sağlamaz.

Jeneratörler

Yineleyicileri uygulamanın bir yolu, kısıtlı bir biçim kullanmaktır. Coroutine, olarak bilinir jeneratör. A ile karşılaştırıldığında altyordam bir jeneratör koroutin kutusu Yol ver değerleri yalnızca bir kez dönmek yerine, arayanına birden çok kez. Çoğu yineleyici doğal olarak üreteç olarak ifade edilebilir, ancak üreteçler çağrılar arasında yerel durumlarını koruduğundan, özellikle karmaşık, durum bilgisi olan yineleyiciler için çok uygundurlar, örneğin: ağaç geçişleri. Yazarlar ve diller arasında değişen "oluşturucu" ve "yineleyici" terimlerinin kullanımında ince farklılıklar ve farklılıklar vardır.[5] İçinde Python bir jeneratör bir yineleyicidir kurucu: bir yineleyici döndüren bir işlev. İçin yineleyici döndüren bir Python oluşturucu örneği Fibonacci sayıları Python'u kullanarak Yol ver ifade şöyledir:

def fibonacci(limit):    a, b = 0, 1    için _ içinde Aralık(limit):        Yol ver a        a, b = b, a + biçin numara içinde fibonacci(100):  # Oluşturucu bir yineleyici oluşturur    Yazdır(numara)

Örtülü yineleyiciler

Gibi bazı nesne yönelimli diller C #, C ++ (sonraki sürümler), Delphi (sonraki sürümler), Git, Java (sonraki sürümler), Lua, Perl, Python, Yakut sağlamak içsel açık bir yineleyici nesnesi olmadan bir kap nesnesinin öğeleri arasında yineleme yolu. Gerçek bir yineleyici nesnesi gerçekte var olabilir, ancak varsa, dilin kaynak kodu içinde açığa çıkmaz.[4][6]

Örtülü yineleyiciler genellikle bir "her biri için "ifade (veya eşdeğeri), aşağıdaki Python örneğindeki gibi:

için değer içinde tekrarlanabilir:    Yazdır(değer)

Python'da yinelenebilir, bir yineleyiciye dönüştürülebilen ve daha sonra for döngüsü sırasında yinelenen bir nesnedir; bu örtülü olarak yapılır.

Veya diğer zamanlarda, bu Ruby örneğinde olduğu gibi, koleksiyon nesnesi tarafından oluşturulabilirler:

tekrarlanabilir.her biri yapmak |değer|  koyar değerson

Bu yineleme stili bazen "dahili yineleme" olarak adlandırılır çünkü kodu yinelenebilir nesnenin bağlamı içinde tam olarak yürütülür (yinelemenin tüm yönlerini kontrol eder) ve programcı yalnızca her adımda yürütülecek işlemi sağlar (bir anonim işlev ).

Destekleyen diller liste anlayışları veya benzer yapılar, Python'da olduğu gibi sonuç listesinin oluşturulması sırasında örtük yineleyicilerden de yararlanabilir:

isimler = [kişi.isim için kişi içinde liste Eğer kişi.erkek]

Bazen örtük gizli doğa yalnızca kısmidir. C ++ dil, örtük yineleme için birkaç işlev şablonuna sahiptir, örneğin her biri için(). Bu işlevler, yine de ilk girdileri olarak açık yineleyici nesneleri gerektirir, ancak sonraki yineleme, kullanıcıya bir yineleme nesnesini göstermez.

Canlı Yayınlar

Yineleyiciler, yararlı bir soyutlamadır. giriş akışları - potansiyel olarak sonsuz sayıda yinelenebilir (ancak indekslenebilir olması gerekmez) bir nesne sağlarlar. Perl ve Python gibi çeşitli diller, akışları yineleyiciler olarak uygular. Python'da yineleyiciler, veri akışlarını temsil eden nesnelerdir.[7] Akışın alternatif uygulamaları şunları içerir: veri tabanlı gibi diller AWK ve sed.

İndekslemeyle zıt

Prosedürel dillerde, alt simge operatörünü ve bir döngü sayacı dizi gibi bir dizideki tüm öğeler arasında döngü yapmak için. İndeksleme bazı nesne yönelimli kaplarla da kullanılabilse de, yineleyicilerin kullanımının bazı avantajları olabilir:[8]

  • Sayma döngüleri, tüm veri yapıları için, özellikle de hiç veya yavaş veri yapıları için uygun değildir. rasgele erişim, sevmek listeler veya ağaçlar.
  • Yineleyiciler, her türden veri yapısını yinelemek için tutarlı bir yol sağlayabilir ve bu nedenle kodu daha okunabilir, yeniden kullanılabilir ve veri yapısındaki bir değişikliğe karşı daha az duyarlı hale getirebilir.
  • Bir yineleyici, öğelerin atlanmamasını veya daha önce ziyaret edilen bir öğeye ikinci kez erişilememesini sağlamak gibi erişim üzerinde ek kısıtlamalar uygulayabilir.
  • Bir yineleyici, yineleyiciyi geçersiz kılmaksızın kap nesnesinin değiştirilmesine izin verebilir. Örneğin, bir yineleyici birinci elemanın ötesine geçtiğinde, öngörülebilir sonuçlarla birlikte kabın başlangıcına ek elemanlar eklemek mümkün olabilir. İndekslemede bu sorunludur çünkü indeks numaralarının değişmesi gerekir.

Bir kabın öğeleri aracılığıyla yinelenirken değiştirilebilmesi yeteneği, modernde gerekli hale gelmiştir. nesne odaklı nesneler arasındaki karşılıklı ilişkilerin ve işlemlerin etkilerinin açık olmayabileceği programlama. Bir yineleyici kullanarak kişi bu tür sonuçlardan izole edilir. Bununla birlikte, bu iddia bir tuz tanesi ile alınmalıdır, çünkü çoğu zaman, verimlilik nedenlerinden ötürü, yineleyici uygulaması, kendisini geçersiz kılmaksızın alttaki kabın modifikasyonunu engelleyecek kadar sıkı bir şekilde kaba bağlıdır.

Bellekteki verilerinin etrafında hareket edebilen kaplar için yineleyiciyi geçersiz kılmamanın tek yolu, kapsayıcı için şu anda canlı olan tüm yineleyicileri bir şekilde takip etmek ve bunları anında güncellemektir. Belirli bir zamanda yineleyicilerin sayısı, bağlı konteynerin boyutuna kıyasla keyfi olarak büyük olabileceğinden, bunların hepsinin güncellenmesi, konteynerin operasyonları üzerindeki karmaşıklık garantisini büyük ölçüde bozacaktır.

Güncellemelerin sayısını kapsayıcı boyutuna bağlı tutmanın alternatif bir yolu, kapsayıcıyla birlikte güncellenmesi gereken kapsayıcı öğelerine dolaylı işaretçilerden oluşan bir tür tutamaç mekanizması kullanmak ve yineleyicilerin, bunlar doğrudan veri öğelerine değil işleyişe sahiptir. Ancak bu yaklaşım yineleyici performansını olumsuz etkileyecektir, çünkü gerçek veri öğesine erişmek için bir çift işaretçi izlemelidir. Bu genellikle arzu edilen bir durum değildir, çünkü yineleyicileri kullanan birçok algoritma, yineleyicilerin veri erişim işlemini ilerleme yönteminden daha sık çağırır. Bu nedenle, çok verimli veri erişimine sahip yineleyicilere sahip olmak özellikle önemlidir.

Sonuç olarak, bu her zaman güvenlik (yineleyiciler her zaman geçerli kalır) ve verimlilik arasında bir değiş tokuştur. Çoğu zaman, ek güvenlik, bunun için ödenecek verimlilik fiyatına değmez. Yineleyicilerin kararlılığına ihtiyaç duyuluyorsa, alternatif bir kap (örneğin bir vektör yerine tekil bağlantılı bir liste) kullanmak daha iyi bir seçim olacaktır (küresel olarak daha verimli).

Yineleyicileri sınıflandırmak

Yineleyici kategorileri

Yineleyiciler, işlevlerine göre kategorize edilebilir. İşte yineleyici kategorilerinin (kapsamlı olmayan) bir listesi:[9][10]

KategoriDiller
Çift yönlü yineleyiciC ++
İleri yineleyiciC ++
Giriş yineleyiciC ++
Çıktı yineleyiciC ++
Rastgele erişim yineleyiciC ++
Önemsiz yineleyiciC ++ (eski STL )[11]

Yineleyici türleri

Bu dillerle kullanılan farklı diller veya kitaplıklar yineleyici türlerini tanımlar. Onlardan bazıları[12]

TürDiller
Dizi yineleyiciPHP, R[13]
Yineleyici önbelleğe almaPHP
Sabit yineleyiciC ++,[14] PHP
Dizin yineleyiciPHP, Python
Yineleyici filtrePHP, R
Yineleyiciyi sınırlaPHP
Liste yineleyiciJava,[6] R
Özyinelemeli dizi yineleyiciPHP
XML yineleyiciPHP

Farklı programlama dillerinde

C # ve diğer .NET dilleri

Yineleyiciler .NET Framework "numaralandırıcılar" olarak adlandırılır ve IEnumerator arayüz. IEnumerator sağlar Sonraki () sonraki öğeye ilerleyen ve koleksiyonun sonuna ulaşılıp ulaşılmadığını gösteren yöntem; a Güncel özellik, o anda işaret edilen öğenin değerini elde etmek için; ve isteğe bağlı Sıfırla() yöntem, numaralandırıcıyı ilk konumuna geri sarmak için. Numaralandırıcı başlangıçta ilk öğeden önceki özel bir değere işaret eder, bu nedenle Sonraki () yinelemeye başlamak için gereklidir.

Numaralandırıcılar genellikle şu çağrı ile elde edilir GetEnumerator () uygulayan bir nesnenin yöntemi IEnumerable arayüz. Konteyner sınıfları genellikle bu arayüzü uygular. Ancak her biri için ifade C # böyle bir yöntem sağlayan herhangi bir nesne üzerinde çalışabilir, uygulamasa bile IEnumerable (ördek yazarak ). Her iki arayüz de şu şekilde genişletildi: genel sürümler .NET 2.0.

Aşağıda, C # 2.0'da yineleyicilerin basit bir kullanımı gösterilmektedir:

// açık sürümIEnumerator<Benim tipim> tekrar = liste.GetEnumerator();süre (tekrar.Sonraki())    Konsol.Yazı çizgisi(tekrar.Güncel);// örtük sürümher biri için (Benim tipim değer içinde liste)    Konsol.Yazı çizgisi(değer);

C # 2.0 ayrıca jeneratörler: dönen olarak bildirilen bir yöntem IEnumerator (veya IEnumerable), ancak "getiri getirisi"Bir nesne örneğini döndürmek yerine bir dizi öğe üretme ifadesi, derleyici tarafından uygun arabirimi uygulayan yeni bir sınıfa dönüştürülecektir.

C ++

C ++ dil, kendi alanında yineleyicilerden Standart Kitaplık ve izin verdikleri işlem repertuarında farklılık gösteren birkaç yineleyici kategorisini açıklar. Bunlar arasında ileri yineleyiciler, çift ​​yönlü yineleyiciler, ve rastgele erişim yineleyiciler, artan olasılıklar sırasına göre. Tüm standart kapsayıcı şablon türleri, bu kategorilerden birinin yinelemelerini sağlar. Yineleyiciler, bir dizinin öğelerine (aslında yineleyiciler olarak kullanılabilir) işaretçileri genelleştirir ve sözdizimleri, dizininkine benzeyecek şekilde tasarlanmıştır. C işaretçi aritmetiği, nerede * ve -> operatörler, yineleyicinin işaret ettiği öğeye başvurmak için kullanılır ve işaretçi aritmetik operatörleri, ++ bir konteynerin geçişinde yineleyicileri değiştirmek için kullanılır.

Yineleyiciler kullanılarak geçiş genellikle tek bir değişken yineleyici ve geçilecek bir aralığı sınırlandırmaya hizmet eden iki sabit yineleyici içerir. Operatörün uygulama sayısı açısından sınırlayıcı yineleyiciler arasındaki mesafe ++ alt sınırı üst sınıra dönüştürmek için gereken, belirlenen aralıktaki öğe sayısına eşittir; ilgili farklı yineleyici değerlerinin sayısı bundan bir fazladır. Geleneksel olarak, alt sınırlayıcı yineleyici, aralıktaki ilk öğeyi "işaret ederken", üst sınırlayıcı yineleyici, aralıktaki herhangi bir öğeyi işaret etmez, bunun yerine aralığın sonunun hemen ötesini gösterir. başla() yöntem alt limiti sağlar ve son() üst sınır. İkincisi, kabın herhangi bir öğesine referans vermez, ancak karşılaştırılabilecek geçerli bir yineleyici değeridir.

Aşağıdaki örnek, bir yineleyicinin tipik bir kullanımını göstermektedir.

std::vektör<int> öğeler;öğeler.Geri itmek(5);  // 'öğeler' vektörüne '5' tamsayı değeri ekleyin.öğeler.Geri itmek(2);  // "öğeler" vektörüne "2" tamsayı değeri ekleyin.öğeler.Geri itmek(9);  // 'öğeler' vektörüne '9' tamsayı değeri ekleyin.için (Oto o = öğeler.başla(); o != öğeler.son(); ++o) {  // 'öğeler'i yineleyin.  std::cout << *o;  // Ve mevcut dizin için 'öğeler'in değerini yazdırın.}// C ++ 11'de, yineleyici kullanmadan aynısı yapılabilir:için (Oto x : öğeler) {  std::cout << x;  // "Öğelerin" her "x" öğesinin değerini yazdırın.}// Her döngü "529" yazdırır.

Yineleyici türleri, birlikte kullanıldıkları kap türlerinden ayrıdır, ancak ikisi genellikle birlikte kullanılır. Yineleyicinin kategorisi (ve dolayısıyla onun için tanımlanan işlemler) genellikle konteynerin türüne bağlıdır, örneğin rastgele erişim yineleyiciler sağlayan diziler veya vektörler, ancak kümeler (uygulama olarak bağlantılı bir yapı kullanan) yalnızca çift yönlü yineleyiciler sağlar. Aynı kap türünün birden fazla ilişkili yineleyici türü olabilir; örneğin std :: vektör konteyner türü, öğelerine (ham) işaretçiler kullanarak (tür * ) veya özel türden değerler std :: vektör :: yineleyicive "ters yineleyiciler" için, normal (ileri) bir geçiş gerçekleştiren bir algoritmanın gerçekte ters yineleyicilerle çağrıldığında ters sırada çapraz geçiş yapacağı şekilde tanımlanmış olan "ters yineleyiciler" için başka bir tür sağlanır. Çoğu konteyner ayrıca ayrı bir const_iterator tür, işaret edilen değerlerin değiştirilmesine izin verecek işlemler kasıtlı olarak tanımlanmamıştır.

Bir kap nesnesinin veya bir dizi öğesinin basit geçişi (bir const_iterator kullanılır) tek başına yineleyiciler kullanılarak yapılabilir. Ancak konteyner türleri, aşağıdaki gibi yöntemler de sağlayabilir: eklemek veya silmek kabın kendi yapısını değiştiren; bunlar konteyner sınıfının yöntemleridir, ancak ek olarak istenen işlemi belirtmek için bir veya daha fazla yineleyici değeri gerektirir. Aynı konteynere aynı anda işaret eden birden fazla yineleyiciye sahip olmak mümkün olsa da, yapı değiştirme işlemleri belirli yineleyici değerlerini geçersiz kılabilir (bunun böyle olup olmayacağı her durum için standart belirler); Geçersiz bir yineleyici kullanmak, tanımlanmamış davranışa yol açacak bir hatadır ve bu tür hataların çalışma zamanı sistemi tarafından sinyallenmesi gerekmez.

Örtük yineleme, standart işlev şablonlarının kullanımıyla C ++ tarafından kısmen desteklenir, örneğin std :: for_each (),std :: kopya ()vestd :: biriktirmek ().

Kullanıldıklarında mevcut yineleyicilerle başlatılmaları gerekir, genellikle başla ve son, yinelemenin gerçekleştiği aralığı tanımlar. Ancak daha sonra yineleme ilerledikçe hiçbir açık yineleyici nesnesi açığa çıkmaz. Bu örnek, her biri için.

Konteyner tipi<Öğe türü> c;  // Herhangi bir standart konteyner türü ItemType öğesi.geçersiz ProcessItem(sabit Öğe türü& ben) {  // Koleksiyonun her bir öğesini işleyecek işlev.  std::cout << ben << std::son;}std::her biri için(c.başla(), c.son(), ProcessItem);  // Her bir yineleme döngüsü için.

Aynı şey kullanılarak elde edilebilir std :: kopyala, geçen bir std :: ostream_iterator üçüncü yineleyici olarak değer:

std::kopya(c.başla(), c.son(), std::ostream_iterator<Öğe türü>(std::cout, " n"));

Dan beri C ++ 11, lambda işlevi sözdizimi, adlandırılmış bir işlev tanımlama ihtiyacını ortadan kaldırarak, işlemin satır içinde yinelenmesini belirtmek için kullanılabilir. Bir lambda işlevi kullanan her yineleme için bir örnek:

Konteyner tipi<Öğe türü> c;  // Herhangi bir standart konteyner türü ItemType öğesi.// Lambda işlevine sahip her bir yineleme döngüsü.std::her biri için(c.başla(), c.son(), [](sabit Öğe türü& ben) { std::cout << ben << std::son; });

Java

Sunulan Java JDK 1.2 sürümü, java.util.Iterator arabirim, konteyner sınıflarının yinelenmesine izin verir. Her biri Yineleyici sağlar Sonraki() ve hasNext () yöntem ve isteğe bağlı olarak destekleyebilir Kaldır() yöntem. Yineleyiciler, karşılık gelen konteyner sınıfı tarafından, genellikle adlı bir yöntemle oluşturulur. yineleyici ().[15]

Sonraki() yöntem yineleyiciyi ilerletir ve yineleyici tarafından gösterilen değeri döndürür. İlk eleman, ilk çağrı üzerine elde edilir. Sonraki(). Kaptaki tüm öğelerin ne zaman ziyaret edildiğini belirlemek için hasNext () test yöntemi kullanılmaktadır. Aşağıdaki örnek, basit bir yineleyici kullanımını gösterir:

Yineleyici tekrar = liste.yineleyici();// Yineleyici  iter = list.iterator (); J2SE 5.0'dasüre (tekrar.hasNext()) {    Sistem.dışarı.Yazdır(tekrar.Sonraki());    Eğer (tekrar.hasNext())        Sistem.dışarı.Yazdır(", ");}

Bunu göstermek için hasNext () tekrar tekrar çağrılabilir, bunu öğeler arasına virgül eklemek için kullanırız, ancak son öğeden sonra kullanmayız.

Bu yaklaşım, gelişmiş işlemi gerçek veri erişiminden tam olarak ayırmaz. Veri elemanının her ilerleme için birden fazla kullanılması gerekiyorsa, geçici bir değişkende depolanması gerekir. Veri erişimi olmadan bir ilerlemeye ihtiyaç duyulduğunda (yani belirli bir veri elemanını atlamak için), erişim yine de gerçekleştirilir, ancak bu durumda döndürülen değer göz ardı edilir.

Destekleyen koleksiyon türleri için, Kaldır() Yineleyicinin yöntemi yineleyiciyi kullanılabilir durumda tutarken en son ziyaret edilen öğeyi kaptan kaldırır. Kabın yöntemlerini çağırarak öğe ekleme veya çıkarma (ayrıca aynı Konu ) yineleyiciyi kullanılamaz hale getirir. Sonraki öğeyi alma girişimi istisnayı atar. Daha fazla öğe kalmadığında da bir istisna atılır (hasNext () önceden yanlış döndürdü).

Ek olarak, java.util.List var java.util.ListIterator benzer bir API ile ancak ileri ve geri yinelemeye izin veren, listedeki mevcut dizinini sağlar ve liste öğesinin konumunda ayarlanmasına izin verir.

J2SE Java 5.0 sürümü, Tekrarlanabilir gelişmiş bir için (her biri için ) koleksiyonlar ve diziler üzerinde yineleme yapmak için döngü. Tekrarlanabilir tanımlar yineleyici () döndüren yöntem Yineleyici. Gelişmiş kullanma için döngü, önceki örnek şu şekilde yeniden yazılabilir:

için (Benim tipim obj : liste) {    Sistem.dışarı.Yazdır(obj);}

Bazı kaplar da eskisini kullanır (1.0'dan beri) Numaralandırma sınıf. Sağlar hasMoreElements () ve nextElement () yöntemler ancak kapsayıcıyı değiştirmek için hiçbir yöntemi yoktur.

Scala

İçinde Scala Yineleyiciler, koleksiyonlara benzer zengin bir yöntem kümesine sahiptir ve doğrudan döngülerde kullanılabilir. Aslında, hem yineleyiciler hem de koleksiyonlar ortak bir temel özellikten miras alır - scala.collection.TraversableOnce. Bununla birlikte, Scala koleksiyonları kitaplığında bulunan harita, toplama, filtreleme vb. Gibi zengin yöntemler kümesi nedeniyle, Scala'da programlama yaparken yineleyicilerle doğrudan uğraşmak genellikle gerekli değildir.

Java yineleyicileri ve koleksiyonları, yalnızca tek bir satır eklenerek otomatik olarak sırasıyla Scala yineleyicilerine ve koleksiyonlarına dönüştürülebilir

ithalat scala.collection.JavaConversions._

dosyaya. JavaConversions nesnesi, bunu yapmak için örtük dönüştürmeler sağlar. Örtülü dönüştürmeler, Scala'nın bir özelliğidir: mevcut kapsamda göründüğünde, aramaları otomatik olarak uygun yerde ilgili ifadelere otomatik olarak ekleyen yöntemler, aksi takdirde yapmayacakları zaman typecheck yapmalarını sağlar.

MATLAB

MATLAB "yerel" dizileri kullanarak hem harici hem de dahili örtük yinelemeyi destekler veya hücre diziler. Çapraz geçişi ilerletme ve sonraki öğeleri talep etme sorumluluğunun kullanıcıya ait olduğu harici yineleme durumunda, kişi bir dizi depolama yapısı içinde bir dizi öğe tanımlayabilir ve öğeleri kullanarak geçiş yapabilir. için-döngü yapısı. Örneğin,

Bir tamsayı dizisi tanımlayındizim = [1,3,5,7,11,13];için n = myArray   % ... n ile bir şeyler yap   disp(n)  Komut Penceresine tamsayı% Yankıson

kullanarak bir tamsayı dizisini dolaşır. için anahtar kelime.

Kullanıcının bir koleksiyonun her öğesi üzerinde gerçekleştirmesi için yineleyiciye bir işlem sağlayabildiği dahili yineleme durumunda, birçok yerleşik işleç ve MATLAB işlevi, bir dizinin her öğesi üzerinde yürütmek ve örtülü olarak karşılık gelen bir çıktı dizisi döndürmek için aşırı yüklenir. . Ayrıca, Dizi eğlencesi ve Cellfun işlevler, "yerel" diziler üzerinde özel veya kullanıcı tanımlı işlemler gerçekleştirmek için kullanılabilir ve hücre sırasıyla diziler. Örneğin,

işlevi simpleFunBir tamsayı dizisi tanımlayındizim = [1,3,5,7,11,13];% Her öğe üzerinde özel bir işlem gerçekleştirin myNewArray = Dizi eğlencesi(@(a)myCustomFun(a),dizim);% Echo sonuç dizisi Komut Penceresine myNewArrayfunction outScalar = myCustomFun (inScalar)% Basitçe 2 ile çarpınoutScalar = 2*inScalar;

birincil bir işlevi tanımlar simpleFun örtük olarak özel alt işlevi uygulayan myCustomFun yerleşik işlev kullanan bir dizinin her öğesine Dizi eğlencesi.

Alternatif olarak, Yineleyici Modelinin özel bir nesne yönelimli MATLAB uygulamasını tanımlayarak, dizi depolama kabının mekanizmalarının kullanıcıdan soyutlanması istenebilir. Harici yinelemeyi destekleyen böyle bir uygulama MATLAB Merkezi Dosya Değişimi öğesinde gösterilmektedir. Tasarım Deseni: Yineleyici (Davranışsal). Bu, MATLAB yazılım sürüm 7.6 (R2008a) ile sunulan yeni sınıf tanımı sözdiziminde yazılmıştır ve tek boyutlu bir hücre dizi gerçeklemesi Özet Veri Tipini Listele (ADT), heterojen (veri türünde) bir öğe kümesini depolamak için bir mekanizma olarak. Açık yönlendirme için işlevsellik sağlar Liste ile geçiş hasNext (), Sonraki() ve Sıfırla() kullanım için yöntemler süre-döngü.

PHP

PHP 's foreach döngüsü 4.0 sürümünde tanıtıldı ve 4.0 Beta 4'te değerler olarak nesnelerle uyumlu hale getirildi.[16] Bununla birlikte, PHP 5'te dahili sürümün tanıtılmasıyla yineleyiciler için destek eklendi.[17] Geçilebilir arayüz.[18] Nesnelerin foreach döngüsü aracılığıyla yinelenmesini sağlayan PHP betiklerinde uygulama için iki ana arabirim şunlardır: Yineleyici ve Yineleyici. İkincisi, uygulama sınıfının gerekli tüm yöntemleri bildirmesini gerektirmez, bunun yerine bir erişimci yöntem (getIterator) bir örneğini döndürür Geçilebilir. Standart PHP Kitaplığı özel yineleyicilerle çalışmak için birkaç sınıf sağlar.[19] PHP ayrıca Jeneratörler 5.5'ten beri.[20]

En basit uygulama, bir diziyi sarmaktır, bu, tip ipucu ve Bilgi gizleme.

ad alanı Wikipedia  Yineleyici;final sınıf ArrayIterator genişler  Yineleyici{    özel dizi $ dizi;    halka açık işlevi __construct(dizi $ dizi)    {        $ this->dizi = $ dizi;    }    halka açık işlevi geri sarma(): geçersiz    {        Eko "geri sarma" , PHP_EOL;        Sıfırla($ this->dizi);    }    halka açık işlevi akım()    {        $ değer = akım($ this->dizi);        Eko "geçerli: {$ değer}", PHP_EOL;        dönüş $ değer;    }    halka açık işlevi anahtar()    {        $ anahtar = anahtar($ this->dizi);        Eko "anahtar: {$ anahtar}", PHP_EOL;        dönüş $ anahtar;    }    halka açık işlevi Sonraki()    {        $ değer = Sonraki($ this->dizi);        Eko "Sonraki: {$ değer}", PHP_EOL;        dönüş $ değer;    }    halka açık işlevi geçerli(): bool    {        $ geçerli = $ this->akım() !== yanlış;        Eko "geçerli:", ($ geçerli ? 'doğru' : 'yanlış'), PHP_EOL;        dönüş $ geçerli;    }}

Örnek sınıfın tüm yöntemleri, eksiksiz bir foreach döngüsünün yürütülmesi sırasında kullanılır (foreach ($ yineleyici olarak $ anahtar => $ akım) {}). Yineleyicinin yöntemleri aşağıdaki sırayla yürütülür:

  1. $ yineleyici-> geri sar () iç yapının baştan başlamasını sağlar.
  2. $ yineleyici-> geçerli () İadeler doğru bu örnekte.
  3. $ yineleyici-> geçerli () döndürülen değer şurada saklanır $ değer.
  4. $ yineleyici-> anahtar () döndürülen değer şurada saklanır $ anahtar.
  5. $ yineleyici-> sonraki () iç yapıda bir sonraki öğeye ilerler.
  6. $ yineleyici-> geçerli () İadeler yanlış ve döngü iptal edilir.

Sonraki örnek, Geçilebilir arabirim, bir Yineleyici foreach döngüsüne döndürülmeden önce veriler üzerinde hareket edecek sınıf. İle birlikte kullanım MYSQLI_USE_RESULT sabit, PHP betiklerinin sonuç kümelerini milyarlarca satırla çok az bellek kullanımıyla yinelemesine izin verir. Bu özellikler PHP'ye veya MySQL sınıfı uygulamalarına özel değildir (ör. PDOStatement sınıf uygulamak Geçilebilir arayüz de).

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);$ mysqli = yeni  mysqli("host.example.com", 'Kullanıcı adı', 'parola', 'veri tabanı ismi');// Yöntem çağrısı tarafından döndürülen  mysqli_result sınıfı, dahili Traversable arabirimini uygular.her biri için ($ mysqli->sorgu("Tablo" dan "a", "b", "c" SEÇİN, MYSQLI_USE_RESULT) gibi $ satır) {    // İlişkilendirilebilir bir dizi olan döndürülen satır üzerinde işlem yapın.}

Python

Yineleyiciler Python dilin temel bir parçasıdır ve çoğu durumda örtük olarak kullanıldıkları için görünmez olurlar. için (her biri için ) ifadesi, içinde liste anlayışları, ve jeneratör ifadeleri. Tüm Python'un standart yerleşik Toplamak türler yinelemeyi ve ayrıca standart kitaplığın parçası olan birçok sınıfı destekler. Aşağıdaki örnek, bir dizi üzerinde tipik örtük yinelemeyi gösterir:

için değer içinde sıra:    Yazdır(değer)

Python sözlükleri (bir tür ilişkilendirilebilir dizi ) ayrıca sözlük anahtarları döndürüldüğünde doğrudan yinelenebilir; ya da öğeler bir sözlüğün yöntemi, karşılık gelen anahtarı, değer çiftlerini bir tuple olarak verdiği yerde yinelenebilir:

için anahtar içinde sözlük:    değer = sözlük[anahtar]    Yazdır(anahtar, değer)
için anahtar, değer içinde sözlük.öğeler():    Yazdır(anahtar, değer)

Yineleyiciler ancak açıkça kullanılabilir ve tanımlanabilir. Yinelenebilir herhangi bir sıra türü veya sınıfı için yerleşik işlev iter () bir yineleyici nesnesi oluşturmak için kullanılır. Yineleyici nesnesi daha sonra Sonraki() işlevini kullanan __Sonraki__() yöntem dahili olarak, kaptaki sonraki öğeyi döndürür. (Önceki ifade Python 3.x için geçerlidir. Python 2.x'te, Sonraki() yöntem eşdeğerdir.) A StopIteration daha fazla öğe kalmadığında istisna ortaya çıkar. Aşağıdaki örnek, açık yineleyiciler kullanan bir dizi üzerinde eşdeğer bir yinelemeyi gösterir:

o = tekrar(sıra)süre Doğru:    Deneyin:        değer = o.Sonraki() Python 2.x içinde #        değer = Sonraki(o) Python 3.x içinde #    dışında StopIteration:        kırmak    Yazdır(değer)

Herhangi bir kullanıcı tanımlı sınıf, standart yinelemeyi (örtük veya açık) bir __iter __ () bir yineleyici nesnesi döndüren yöntem. Yineleyici nesnesinin daha sonra bir __Sonraki__() sonraki öğeyi döndüren yöntem.

Python'un jeneratörler bu yinelemeyi uygula protokol.

Yakut

Ruby yineleyicileri oldukça farklı bir şekilde uygular; tüm yinelemeler, geri arama kapanışlarını kapsayıcı yöntemlerine geçirerek yapılır - bu şekilde Ruby yalnızca temel yinelemeyi değil, aynı zamanda işlev eşleme, filtreler ve azaltma gibi çeşitli yineleme modellerini de uygular. Ruby ayrıca temel yineleme yöntemi için alternatif bir sözdizimi destekler her biriaşağıdaki üç örnek eşdeğerdir:

(0...42).her biri yapmak |n|  koyar nson

…ve…

için n içinde 0...42  koyar nson

hatta daha kısa

42.zamanlar yapmak |n|  koyar nson

Ruby ayrıca, Numaralandırıcıları kullanarak ve #sonraki yöntemlerini çağırarak veya yukarıdaki gibi her biri için bir yaparak sabit listeler üzerinde yineleme yapabilir.

Pas, paslanma

Rust ile vektörler üzerinde yineleme yapabilir veya kendi yineleyicileri oluşturabilirsiniz.Her yineleyicide bağdaştırıcılar vardır (harita, filtre, atlama, alma, ...).

içinniçinde0..42{println!("{}",n);}

Fibonacci () 'nin altında özel bir yineleyici bulunur.

içinbeniçindefibonacci().atlama(4).almak(4){println!("{}",ben);}

Ayrıca bakınız

Referanslar

  1. ^ Gatcomb, Joshua. "Yineleyicileri Anlama ve Kullanma". Perl.com. Arşivlenen orijinal 2005-06-16 tarihinde. Alındı 2012-08-08. Kullanıcı tanımlı bir yineleyici genellikle çalıştırıldığında bir listedeki sonraki öğeyi hesaplayan ve onu döndüren bir kod referansı biçimini alır. Yineleyici listenin sonuna ulaştığında, üzerinde anlaşılan bir değer döndürür.
  2. ^ a b Watt, Stephen M. "Genel Yineleme için Bir Teknik ve Optimizasyonu" (PDF). Western Ontario Üniversitesi, Bilgisayar Bilimleri Bölümü. Arşivlenen orijinal (PDF) 2006-09-16 tarihinde. Alındı 2012-08-08. Yineleyiciler, iç temsillerini açığa çıkarmadan soyut veri yapıları üzerinde döngüye izin veren yapılar olarak tanıtıldı.
  3. ^ Alex Allain. "STL Yineleyiciler". Cprogramming.com - C ve C ++ kaynağınız. Alındı 2012-08-08. Yineleyiciyi, daha büyük bir öğe konteynerinin parçası olan bir öğeyi işaret ediyormuş gibi düşünebilirsiniz.
  4. ^ a b "Harici yineleyici ile dahili yineleyici arasındaki fark". CareerRide.COM. 2009-04-03. Arşivlenen orijinal 2009-04-03 tarihinde. Alındı 2012-08-08. Bir iç yineleyici, yineleme mantığına sahip sınıfın üye işlevleri tarafından gerçekleştirilir. Harici bir yineleyici, yineleme mantığına sahip nesneye eklenebilen ayrı bir sınıf tarafından gerçekleştirilir. Harici yineleyicinin avantajı, birçok yineleyicinin mevcut veya aynı nesne üzerinde aynı anda etkin hale getirilebilmesidir.
  5. ^ Watt, Stephen M. "Genel Yineleme için Bir Teknik ve Optimizasyonu" (PDF). Western Ontario Üniversitesi, Bilgisayar Bilimleri Bölümü. Arşivlenen orijinal (PDF) 2006-09-16 tarihinde. Alındı 2012-08-08. Bazı yazarlar yineleyici terimini, bazıları da üretici terimini kullanır. Bazıları ikisi arasında ince ayrımlar yapar.
  6. ^ a b Freeman, Eric; Freeman, Elisabeth; Kathy, Sierra; Bert, Bates (2004). Hendrickson, Mike; Loukides, Mike (editörler). "Önce Baş Tasarım Modelleri" (ciltsiz). 1. O'REILLY: 338. ISBN  978-0-596-00712-6. Alındı 2012-08-09. Alıntı dergisi gerektirir | günlük = (Yardım)
  7. ^ "Sözlük - Python 3.8.4 belgeleri". Alındı 2020-07-15.
  8. ^ Vecerina, Ivan (2006/02/01). "indeks - yineleyici". BYTES. Arşivlenen orijinal 2006-02-01 tarihinde. Alındı 2012-08-08. Bir dizin yalnızca rastgele erişimi (yani belirli bir konumdaki bir öğeye doğrudan erişim) (verimli bir şekilde) destekleyen kaplar için kullanılabilir. Yineleyici daha genel bir kavramdır. Yineleyiciler, bağlantılı listelerin, dosyaların ve bir dizi başka veri yapısının verimli geçişini sağlar. Genellikle daha verimli kod üretilmesine yol açar.
  9. ^ Kevin Waterson. "C ++ Yineleyici: Yineleyici-Kategori" (Almanca'da). cppreference.com. Alındı 2012-08-09.
  10. ^ Kevin Waterson. "Yineleyiciler: Kavramlar". sgi. Alındı 2012-08-09.
  11. ^ larsmans (2011-03-06). "Yineleyici türleri: Çıktıya karşı girdi, iletiye karşılık rastgele erişim yineleyicisi". stackoverflow. Arşivlenen orijinal 2011-03-06 tarihinde. Alındı 2012-08-09.
  12. ^ Kevin Waterson. "SPL'ye Giriş: Standart PHP Kitaplığına (SPL) Giriş". PHPRO.ORG. Alındı 2012-08-09.
  13. ^ Collier, Andrew. "R'deki yineleyiciler". Alındı 16 Kasım 2013.
  14. ^ "concurrent_unordered_set Şablon Sınıfı". Açık Kaynak için Intel Threading Yapı Taşları. Arşivlenen orijinal 2015-05-01 tarihinde. Alındı 2012-08-09. • Yineleyici türleri yineleyici ve yapılandırıcı ileri yineleyici kategorisindedir
  15. ^ "java.util: Arayüz Yineleyici : Yöntem Özeti". Oracle. Alındı 2012-08-08.
  16. ^ "PHP 4 ChangeLog". PHP Grubu. 2000-02-20. Alındı 2015-10-13.
  17. ^ Dahili, arayüzün PHP betiklerinde, yalnızca C (programlama dili) kaynak.
  18. ^ "Geçilebilir arayüz". PHP Grubu. Alındı 2015-10-13.
  19. ^ "Yineleyiciler". PHP Grubu. Alındı 2015-10-13.
  20. ^ "PHP 5 ChangeLog". PHP Grubu. 2013-06-20. Alındı 2015-10-13.

Dış bağlantılar