জাভা-এর প্রতিটি লুপের জন্য একটি পুনরাবৃত্তি-কাউন্টারে অ্যাক্সেস করার কোনও উপায় আছে?


273

জাভা-এর প্রতিটি লুপের কোনও উপায় আছে?

for(String s : stringArray) {
  doSomethingWith(s);
}

ইতিমধ্যে কতবার লুপটি প্রক্রিয়াভুক্ত হয়েছে তা জানতে?

পুরাতন এবং সুপরিচিত for(int i=0; i < boundary; i++)- লুপটি ব্যবহার করা বাদ দিয়ে তৈরি const

int i = 0;
for(String s : stringArray) {
  doSomethingWith(s);
  i++;
}

প্রতিটি লুপের জন্য এই জাতীয় কাউন্টার উপলব্ধ থাকার একমাত্র উপায়?


2
আরেকটি দু: খের বিষয় যে আপনার, লুপ বাইরে লুপ ভেরিয়েবল ব্যবহার করতে পারে নাType var = null; for (var : set) dosomething; if (var != null) then ...
Val,

@ ভাল যদি না রেফারেন্স কার্যকর চূড়ান্ত হয়। এই বৈশিষ্ট্যটি কীভাবে ব্যবহার করতে হয় তার জন্য আমার উত্তর দেখুন
rmuller

উত্তর:


205

না, তবে আপনি নিজের কাউন্টার সরবরাহ করতে পারেন।

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


5
এর জন্য রুবির একটি নির্মাণ রয়েছে এবং for(int idx=0, String s; s : stringArray; ++idx) doSomethingWith(s, idx);
জাভাও

9
উত্তরটি "না, দিয়ে শুরু হওয়া উচিত তবে আপনি নিজের কাউন্টার সরবরাহ করতে পারেন।"
ব্যবহারকারী 1094206

1
এফওয়াইআই @ নিকোলাসডিপিপিয়াজা রুবিতে একটি each_with_indexলুপ পদ্ধতি রয়েছে Enumerable। Apidock.com/ruby/Enumerable/each_with_index দেখুন
saywhatnow

@ সাইয়াঘটনা হ্যাঁ এটাই আমার দুঃখের অর্থ - আমি পূর্ববর্তী মন্তব্যটি করার সময় আমি কী ধূমপান করছিলাম তা নিশ্চিত নন
নিকোলাস ডিপিয়াজ়া

2
"এর কারণ হ'ল অভ্যন্তরীণভাবে প্রতিটি লুপের একটি পাল্টা নেই"। "জাভা বিকাশকারীরা প্রোগ্রামারটিকে forলুপের অভ্যন্তরে প্রাথমিক মান সহ সূচক পরিবর্তনশীল নির্দিষ্ট করতে দেয় না" হিসাবে পড়তে হবে , এমন কিছুfor (int i = 0; String s: stringArray; ++i)
izogfif

64

আরও একটি উপায় আছে।

প্রদত্ত যে আপনি নিজের Indexক্লাস এবং একটি স্থির পদ্ধতি লিখেছেন Iterableযা এই শ্রেণীর একাধিক উদাহরণ আপনি দিতে পারেন

for (Index<String> each: With.index(stringArray)) {
    each.value;
    each.index;
    ...
}

যেখানে বাস্তবায়ন With.indexহ'ল এরকম কিছু

class With {
    public static <T> Iterable<Index<T>> index(final T[] array) {
        return new Iterable<Index<T>>() {
            public Iterator<Index<T>> iterator() {
                return new Iterator<Index<T>>() {
                    index = 0;
                    public boolean hasNext() { return index < array.size }
                    public Index<T> next() { return new Index(array[index], index++); }
                    ...
                }
            }
        }
    }
}

7
ঝরঝরে ধারণা। আমি সূচক শ্রেণীর স্বল্প জীবিত অবজেক্ট তৈরির জন্য না হলে আমি উজ্জীবিত হত।
mR_fr0g

3
@ mR_fr0g চিন্তা করবেন না, আমি এটি বেঞ্চমার্ক করেছি এবং এই সমস্ত অবজেক্ট তৈরি করা প্রতিটি পুনরাবৃত্তির জন্য একই অবজেক্টটি পুনরায় ব্যবহার করার চেয়ে ধীর নয়। কারণটি হ'ল এই সমস্ত বস্তুগুলি কেবলমাত্র এডেন স্পেসে বরাদ্দ করা হয় এবং কখনই জীবনের দীর্ঘস্থায়ী হয় না। সুতরাং এগুলি বরাদ্দ করা যেমন তত দ্রুত যেমন স্থানীয় ভেরিয়েবলগুলি বরাদ্দ করা।
akuhn

1
@akuhn অপেক্ষা করুন ইডেন স্পেসের অর্থ এই নয় যে কোনও জিসি পুনরায় প্রাপ্ত হয় না। একেবারে বিপরীতভাবে, আপনাকে নির্মাণকারীকে ডাকতে হবে, খুব শীঘ্রই জিসি দিয়ে স্ক্যান করতে হবে এবং চূড়ান্ত করতে হবে। এটি কেবল সিপিইউ লোড করে না তবে সর্বদা ক্যাশে অবৈধ করে তোলে। স্থানীয় ভেরিয়েবলের জন্য এর মতো কিছুই প্রয়োজন হয় না। আপনি কেন বলেন যে এটি "একই"?
Val,

7
আপনি যদি এর মতো স্বল্পজীবী জিনিসগুলির পারফরম্যান্স সম্পর্কে উদ্বিগ্ন হন তবে আপনি এটি ভুল করছেন। পারফরম্যান্সটি ... পড়ার প্রথমটি নিয়ে চিন্তা করার জন্য সর্বশেষ বিষয় হওয়া উচিত। এটি আসলে একটি বেশ ভাল নির্মাণ।
বিল কে

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

47

সবচেয়ে সহজ সমাধানটি হ'ল এইভাবে আপনার নিজের কাউন্টার চালানো:

int i = 0;
for (String s : stringArray) {
    doSomethingWith(s, i);
    i++;
}

এই জন্য কারণ আছে, কারণ কোন প্রকৃত গ্যারান্টি যে একটি সংগ্রহ (যা যে বৈকল্পিক আইটেম foriterates বেশি) এমনকি আছে একটি সূচক, অথবা এমনকি একটি আছে সংজ্ঞায়িত অর্ডার (যখন আপনি Add or Remove উপাদানের কিছু সংগ্রহ ক্রম পরিবর্তন হতে পারে)।

উদাহরণস্বরূপ, নিম্নলিখিত কোডটি দেখুন:

import java.util.*;

public class TestApp {
  public static void AddAndDump(AbstractSet<String> set, String str) {
    System.out.println("Adding [" + str + "]");
    set.add(str);
    int i = 0;
    for(String s : set) {
        System.out.println("   " + i + ": " + s);
        i++;
    }
  }

  public static void main(String[] args) {
    AbstractSet<String> coll = new HashSet<String>();
    AddAndDump(coll, "Hello");
    AddAndDump(coll, "My");
    AddAndDump(coll, "Name");
    AddAndDump(coll, "Is");
    AddAndDump(coll, "Pax");
  }
}

আপনি যখন এটি চালান, আপনি এমন কিছু দেখতে পাবেন:

Adding [Hello]
   0: Hello
Adding [My]
   0: Hello
   1: My
Adding [Name]
   0: Hello
   1: My
   2: Name
Adding [Is]
   0: Hello
   1: Is
   2: My
   3: Name
Adding [Pax]
   0: Hello
   1: Pax
   2: Is
   3: My
   4: Name

নির্দেশ করে যে, ঠিক তাই, অর্ডারটি কোনও সেটের প্রধান বৈশিষ্ট্য হিসাবে বিবেচিত হয় না।

ম্যানুয়াল কাউন্টার ছাড়াই এটি করার অন্যান্য উপায় রয়েছে তবে এটি সন্দেহজনক সুবিধার জন্য মোটামুটি কাজ।


2
এটি এখনও তালিকা এবং পরীক্ষণযোগ্য ইন্টারফেসের সাথেও সবচেয়ে পরিষ্কার সমাধান বলে মনে হচ্ছে।
জোশুয়া পিন্টার

27

ব্যবহার lambdas এবং কার্মিক ইন্টারফেসগুলি মধ্যে জাভা 8 তোলে নতুন লুপ বিমূর্ত সম্ভব তৈরি করা। আমি সূচক এবং সংগ্রহের আকারের সাহায্যে একটি সংগ্রহকে লুপ করতে পারি:

List<String> strings = Arrays.asList("one", "two","three","four");
forEach(strings, (x, i, n) -> System.out.println("" + (i+1) + "/"+n+": " + x));

কোন ফলাফল:

1/4: one
2/4: two
3/4: three
4/4: four

যা আমি হিসাবে প্রয়োগ করেছি:

   @FunctionalInterface
   public interface LoopWithIndexAndSizeConsumer<T> {
       void accept(T t, int i, int n);
   }
   public static <T> void forEach(Collection<T> collection,
                                  LoopWithIndexAndSizeConsumer<T> consumer) {
      int index = 0;
      for (T object : collection){
         consumer.accept(object, index++, collection.size());
      }
   }

সম্ভাবনার শেষ নেই. উদাহরণস্বরূপ, আমি একটি বিমূর্ততা তৈরি করেছি যা কেবলমাত্র প্রথম উপাদানটির জন্য একটি বিশেষ ফাংশন ব্যবহার করে:

forEachHeadTail(strings, 
                (head) -> System.out.print(head), 
                (tail) -> System.out.print(","+tail));

যা কমা দ্বারা পৃথক করা তালিকাটি সঠিকভাবে মুদ্রণ করে:

one,two,three,four

যা আমি হিসাবে প্রয়োগ করেছি:

public static <T> void forEachHeadTail(Collection<T> collection, 
                                       Consumer<T> headFunc, 
                                       Consumer<T> tailFunc) {
   int index = 0;
   for (T object : collection){
      if (index++ == 0){
         headFunc.accept(object);
      }
      else{
         tailFunc.accept(object);
      }
   }
}

গ্রন্থাগারগুলি এই ধরণের জিনিসগুলি করতে পপ আপ করা শুরু করবে বা আপনি নিজেরাই রোল করতে পারেন।


3
পোস্টটির সমালোচনা নয় (এটি "এটি করার দুর্দান্ত উপায়" আজকের দিনে আমি অনুমান করি), তবে লুপের জন্য একটি সহজ পুরানো বিদ্যালয়ের চেয়ে এটি কীভাবে সহজ / উন্নত তা দেখার জন্য আমি সংগ্রাম করছি: জন্য (int i = 0; i < list.size (); i++)} grand এমনকি ঠাকুরমাও এটি বুঝতে পারতেন এবং ল্যাম্বদা যে সিনট্যাক্স এবং অস্বাভাবিক অক্ষর ব্যবহার করেন তা ছাড়া টাইপ করা সম্ভবত সহজ। আমাকে ভুল করবেন না, আমি নির্দিষ্ট জিনিসের জন্য ল্যাম্বডাস ব্যবহার করতে পছন্দ করি (কলব্যাক / ইভেন্ট হ্যান্ডলার ধরণের ধরণ) তবে আমি কেবল এই জাতীয় ক্ষেত্রে ব্যবহার বুঝতে পারি না। দুর্দান্ত সরঞ্জাম, কিন্তু এটি সর্বদা ব্যবহার করে , আমি ঠিক করতে পারি না।
ম্যানিয়াস

আমি মনে করি, তালিকার বাইরে থেকে বাইরের ওয়ান ইনডেক্স / আন্ডারফ্লোগুলিতে কিছুটা এড়ানো। তবে উপরে পোস্ট করা বিকল্প রয়েছে: int i = 0; (স্ট্রিং গুলি: স্ট্রিংআরে) {ডসসোমথিংথথ (গুলি, আই); আমি ++,; }
ম্যানিয়াস

21

জাভা 8 Iterable#forEach()/ Map#forEach()পদ্ধতিটি চালু করেছে , যা প্রতিটি লুপের জন্য "ধ্রুপদী" তুলনায় অনেক Collection/ Mapবাস্তবায়নের জন্য আরও কার্যকর । যাইহোক, এছাড়াও এই ক্ষেত্রে একটি সূচক সরবরাহ করা হয় না। এখানে কৌশলটি AtomicIntegerল্যাম্বডা এক্সপ্রেশনটির বাইরে ব্যবহার করা । দ্রষ্টব্য: ল্যাম্বডা এক্সপ্রেশনটির মধ্যে ব্যবহৃত ভেরিয়েবলগুলি কার্যকরভাবে চূড়ান্ত হওয়া উচিত, এজন্য আমরা কোনও সাধারণ ব্যবহার করতে পারি না int

final AtomicInteger indexHolder = new AtomicInteger();
map.forEach((k, v) -> {
    final int index = indexHolder.getAndIncrement();
    // use the index
});

16

আমি ভয় করি যে এটি দিয়ে সম্ভব নয় foreach। তবে আমি আপনাকে লুপের জন্য একটি সাধারণ পুরানো-স্টাইলযুক্ত প্রস্তাব করতে পারি :

    List<String> l = new ArrayList<String>();

    l.add("a");
    l.add("b");
    l.add("c");
    l.add("d");

    // the array
    String[] array = new String[l.size()];

    for(ListIterator<String> it =l.listIterator(); it.hasNext() ;)
    {
        array[it.nextIndex()] = it.next();
    }

লক্ষ্য করুন যে, তালিকা ইন্টারফেস আপনাকে অ্যাক্সেস দেয় it.nextIndex()

(সম্পাদনা)

আপনার পরিবর্তিত উদাহরণের জন্য:

    for(ListIterator<String> it =l.listIterator(); it.hasNext() ;)
    {
        int i = it.nextIndex();
        doSomethingWith(it.next(), i);
    }

9

পরিবর্তনগুলির মধ্যে Sunএকটি বিবেচনা করে Java7তা হ'ল Iteratorফোরচ লুপগুলিতে অভ্যন্তরের অ্যাক্সেস সরবরাহ করা । বাক্যবিন্যাসটি এরকম কিছু হবে (যদি এটি গ্রহণ করা হয়):

for (String str : list : it) {
  if (str.length() > 100) {
    it.remove();
  }
}

এটি সিনট্যাকটিক চিনি, তবে দৃশ্যত এই বৈশিষ্ট্যটির জন্য প্রচুর অনুরোধ করা হয়েছিল। তবে এটি অনুমোদিত হওয়ার আগ পর্যন্ত আপনাকে পুনরাবৃত্তিগুলি নিজেই গণনা করতে হবে, বা একটি দিয়ে লুপের জন্য একটি নিয়মিত ব্যবহার করতে হবে Iterator


7

আইডোমেটিক সলিউশন:

final Set<Double> doubles; // boilerplate
final Iterator<Double> iterator = doubles.iterator();
for (int ordinal = 0; iterator.hasNext(); ordinal++)
{
    System.out.printf("%d:%f",ordinal,iterator.next());
    System.out.println();
}

গুয়ারা পেয়ারা আলোচনায় কেন তারা সরবরাহ করেনি সে সম্পর্কে এই সমাধানটিই আসলে সমাধান CountingIterator


4

যদিও এটি অর্জনের জন্য আরও অনেকগুলি উপায় উল্লেখ করা হয়েছে, তবে আমি কিছু অসন্তুষ্ট ব্যবহারকারীদের জন্য আমার উপায় ভাগ করব। আমি জাভা 8 ইন্টারস্ট্রিম বৈশিষ্ট্যটি ব্যবহার করছি।

1. অ্যারে

Object[] obj = {1,2,3,4,5,6,7};
IntStream.range(0, obj.length).forEach(index-> {
    System.out.println("index: " + index);
    System.out.println("value: " + obj[index]);
});

2. তালিকা

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");

IntStream.range(0, strings.size()).forEach(index-> {
    System.out.println("index: " + index);
    System.out.println("value: " + strings.get(index));
});

2

যদি প্রতিটি লুপের জন্য কাউন্টারের প্রয়োজন হয় তবে আপনাকে নিজেকে গুনতে হবে। আমি যতদূর জানি কাউন্টারে কোনও বিল্ট নেই।


(আমি প্রশ্নটিতে এই বাগটি স্থির করে দিয়েছি))
টম হাটিন -

1

উত্তর প্যাক করার জন্য একটি "বৈকল্পিক" আছে ... ;-)

int i = -1;
for(String s : stringArray) {
    doSomethingWith(s, ++i);
}

3
কৌতূহলী, এটি পরিষ্কার, আপাতদৃষ্টিতে পরিষ্কার i=0; i++;পদ্ধতির মাধ্যমে ব্যবহার করার কোনও সুবিধা আছে কি?
জোশুয়া পিন্টার

1
আমি অনুমান করি যে আপনার যদি সুযোগের জন্য doSomething এর পরে আই সূচকটি আবার ব্যবহার করতে হয়।
gcedo

1

এমন পরিস্থিতিতে যেখানে আমার মাঝে মাঝে কেবল সূচি প্রয়োজন, যেমন ধরার ধরণের মতো, আমি মাঝে মাঝে সূচকও ব্যবহার করব।

for(String s : stringArray) {
  try {
    doSomethingWith(s);
  } catch (Exception e) {
    LOGGER.warn("Had some kind of problem with string " +
      stringArray.indexOf(s) + ": " + s, e);
  }
}

2
সতর্কতা অবলম্বন করুন যে এটির একটি .equals () প্রয়োজন - অ্যারে অবজেক্টগুলি কার্যকর করা যা কোনও নির্দিষ্ট বস্তুকে অনন্যভাবে সনাক্ত করতে পারে। স্ট্রিংসের ক্ষেত্রে এটি নয় , যদি কোনও নির্দিষ্ট স্ট্রিং একাধিকবার অ্যারেতে থাকে তবে আপনি কেবল প্রথম উপস্থিতির সূচকটি পেয়ে যাবেন, এমনকি যদি আপনি একই স্ট্রিংয়ের পরে কোনও আইটেমটিতে ইতিমধ্যে পুনরাবৃত্তি করছিলেন।
Kosi2801

-1

সর্বোত্তম এবং অনুকূলিত সমাধানটি নিম্নলিখিত জিনিসটি করা:

int i=0;

for(Type t: types) {
  ......
  i++;
}

যেখানে টাইপ কোনও ডেটা টাইপ হতে পারে এবং প্রকারভেদে এমন পরিবর্তনশীল হয় যার উপর আপনি লুপের জন্য আবেদন করছেন।


আপনার উত্তরটি একটি পুনরায় উত্পাদনযোগ্য কোড ফর্ম্যাটে সরবরাহ করুন।
নরমন দারবিশ

এটি হ'ল উপায়, যার জন্য বিকল্প সমাধান চাওয়া হয়েছে। প্রশ্নটি ধরণের সম্পর্কে নয় তবে ম্যানুয়ালি গণনা করার চেয়ে পৃথক উপায়ে লুপ কাউন্টারটিতে অ্যাক্সেসের সম্ভাবনা সম্পর্কে।
Kosi2801

-4

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

দ্রষ্টব্য: এটি ধরে নেয় যে তালিকার উপাদানগুলি অনন্য, বা এটি অ-অনন্য কিনা তা বিবেচ্য নয় (কারণ সেক্ষেত্রে এটি প্রথম অনুলিপিটির সূচি ফিরে আসবে)।

এমন পরিস্থিতিতে রয়েছে যা যথেষ্ট হবে ...


9
পুরো লুপটির জন্য ও (এন) এর কাছে একটি পারফরম্যান্স পৌঁছে দিয়ে এমন কিছু পরিস্থিতি কল্পনা করা খুব কঠিন যেখানে এটি অন্য যে কোনও কিছুর চেয়ে সেরা হবে। দুঃখিত।
Kosi2801

-5

আমি কীভাবে এটি করেছি তার উদাহরণ এখানে। এটি প্রতিটি লুপের জন্য সূচক পায় gets আশাকরি এটা সাহায্য করবে.

public class CheckForEachLoop {

    public static void main(String[] args) {

        String[] months = new String[] { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST",
                "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" };
        for (String s : months) {
            if (s == months[2]) { // location where you can change
              doSomethingWith(s); // however many times s and months
                                  // doSomethingWith(s) will be completed and 
                                  // added together instead of counter
            }

        }
        System.out.println(s); 


    }
}

1
দুঃখিত, এটি প্রশ্নের উত্তর দিচ্ছে না। এটি সামগ্রী অ্যাক্সেস সম্পর্কে নয় তবে একটি কাউন্টার সম্পর্কে যে লুপটি ইতিমধ্যে কতবার পুনরাবৃত্তি হয়েছে।
Kosi2801

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