স্পারসিআরির মাধ্যমে পুনরাবৃত্তি কীভাবে করবেন?


311

জাভা স্পার্সআরে (অ্যান্ড্রয়েডের জন্য) দিয়ে পুনরাবৃত্তি করার কোনও উপায় আছে কি? আমি sparsearrayসূচী দ্বারা সহজেই মানগুলি ব্যবহার করতাম । একটাও পেলাম না।


30
বাহ, একটি সম্পূর্ণ অবহেলিত শ্রেণীর কথা বলুন ,

1
আপনি এমন কোনও ব্যবহার করতে পারেন TreeMap<Integer, MyType>যা আপনাকে কী দ্বারা ক্রমে পুনরাবৃত্তি করতে দেয়। যেমন বলা হয়েছে, স্পার্সআরে হ্যাশম্যাপের চেয়ে আরও দক্ষ হওয়ার জন্য ডিজাইন করা হয়েছে তবে এটি পুনরাবৃত্তির অনুমতি দেয় না।
জন বি

2
এটি খুব সম্ভবত খুব সম্ভবত আপনার পছন্দমতো মানচিত্রের ইমপ্লের পারফরম্যান্স আপনার অ্যাপ্লিকেশনটিতে বাধা হয়ে দাঁড়াবে।
জেফ্রি ব্লাটম্যান

3
@ জেফ্রি ব্ল্যাটম্যান এর অর্থ এই নয় যে এটি সঠিকভাবে যখন সঠিকভাবে উপযুক্ত তখন ব্যবহার করা উচিত।
হিমশীতল

1
@ ফ্রস্টাইমারভেলেস বলছেন যে এটি দুটি দ্বিগুণ দ্রুত, এর অর্থ সম্ভবত 10 এসএম এরও কম সঞ্চয় হবে। অ্যাপ্লিকেশনটির গ্র্যান্ডার স্কিমের সাথে কি 10 মাইল প্রাসঙ্গিক? এমন একটি সাব-অনুকূল ইন্টারফেসটি ব্যবহার করা কি বোঝার এবং বজায় রাখা শক্ত? আমি এই জিনিসগুলির উত্তর জানি না, তবে উত্তরটি "স্পার্স অ্যারে নির্বিশেষে ব্যবহার করুন" নয়।
জেফ্রি ব্লাটম্যান

উত্তর:


536

আমি সমাধান খুঁজে পেয়েছি বলে মনে হচ্ছে। আমি keyAt(index)ফাংশনটি সঠিকভাবে লক্ষ্য করিনি ।

সুতরাং আমি এই জাতীয় কিছু নিয়ে যাব:

for(int i = 0; i < sparseArray.size(); i++) {
   int key = sparseArray.keyAt(i);
   // get the object by the key.
   Object obj = sparseArray.get(key);
}

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

12
অ্যারের আকারকে পূর্বনির্ধারণ করা এবং লুপে ধ্রুবক মান ব্যবহার করা ভাল।
দিমিত্রি জায়েটসেভ

25
এখানে সরাসরি ভ্যালুএট ফাংশন ব্যবহার করা কি সহজ হবে?
মিলান কারস্টিক

34
এটি লুপের Object obj = sparseArray.valueAt(i);
ফ্লোরিয়ান

27
valueAt(i)দ্রুত চেয়ে get(key), কারণ valueAt(i)এবং keyAt(i)উভয় হে (1) কিন্তু get(key)হয় হে (log2 ঢ) , তাই আমি অবশ্যই সবসময় ব্যবহার করেন valueAt
মেকি

180

যদি আপনি কীগুলির বিষয়ে চিন্তা না করেন valueAt(int)তবে মানগুলি সরাসরি অ্যাক্সেস করার জন্য স্পারস অ্যারেটি দিয়ে পুনরাবৃত্তি করার সময় এটি ব্যবহার করা যেতে পারে।

for(int i = 0, nsize = sparseArray.size(); i < nsize; i++) {
    Object obj = sparseArray.valueAt(i);
}

7
যদি আপনার পুনরাবৃত্তি কীগুলির বিষয়ে যত্নশীল না হয়, যেমন: একটি নির্দিষ্ট মানটির একটি লুপ গণনা করার ঘটনাটি ভ্যালুএ্যাট () গ্রহণযোগ্য (এবং স্বীকৃত সমাধানের চেয়ে দ্রুত) কার্যকর।
সোগগার

2
sparseArray.size()একটি ভেরিয়েবল নিন যাতে size()প্রতিবার এটি কল হয় না ।
প্রতীক বুটানি

4
আকার () কে একটি ভেরিয়েবলের অনুলিপি করতে পারা যায় না। আপনি কেবল আকার () পদ্ধতির কোডটি দেখছেন কিনা তা পরীক্ষা করা সহজ। আপনি কেন এই জাতীয় পরামর্শ দেওয়ার আগে আপনি কেন করেননি তা আমি বুঝতে পারি না ... আমার 20 বছর আগে একটি সময় মনে আছে যেখানে আপনি সরল লিঙ্কযুক্ত তালিকাগুলি রেখেছিলেন যা আপনি যখনই চেয়েছিলেন প্রতিটি সময়ই তাদের আকারটি সত্যিই গণনা করতে হয়েছিল তবে আমি বিশ্বাস করি না এই জাতীয় জিনিস এখনও বিদ্যমান ...
অবিশ্বাস্য জানুয়ারী

এটি কী ক্রমে থাকার নিশ্চয়তা রয়েছে?
হিউঘুঘটওটল

18

ওওর আপনি কেবল নিজের তালিকা তালিকা প্রস্তুতকারী:

public final class SparseArrayIterator<E> implements ListIterator<E> {

private final SparseArray<E> array;
private int cursor;
private boolean cursorNowhere;

/**
 * @param array
 *            to iterate over.
 * @return A ListIterator on the elements of the SparseArray. The elements
 *         are iterated in the same order as they occur in the SparseArray.
 *         {@link #nextIndex()} and {@link #previousIndex()} return a
 *         SparseArray key, not an index! To get the index, call
 *         {@link android.util.SparseArray#indexOfKey(int)}.
 */
public static <E> ListIterator<E> iterate(SparseArray<E> array) {
    return iterateAt(array, -1);
}

/**
 * @param array
 *            to iterate over.
 * @param key
 *            to start the iteration at. {@link android.util.SparseArray#indexOfKey(int)}
 *            < 0 results in the same call as {@link #iterate(android.util.SparseArray)}.
 * @return A ListIterator on the elements of the SparseArray. The elements
 *         are iterated in the same order as they occur in the SparseArray.
 *         {@link #nextIndex()} and {@link #previousIndex()} return a
 *         SparseArray key, not an index! To get the index, call
 *         {@link android.util.SparseArray#indexOfKey(int)}.
 */
public static <E> ListIterator<E> iterateAtKey(SparseArray<E> array, int key) {
    return iterateAt(array, array.indexOfKey(key));
}

/**
 * @param array
 *            to iterate over.
 * @param location
 *            to start the iteration at. Value < 0 results in the same call
 *            as {@link #iterate(android.util.SparseArray)}. Value >
 *            {@link android.util.SparseArray#size()} set to that size.
 * @return A ListIterator on the elements of the SparseArray. The elements
 *         are iterated in the same order as they occur in the SparseArray.
 *         {@link #nextIndex()} and {@link #previousIndex()} return a
 *         SparseArray key, not an index! To get the index, call
 *         {@link android.util.SparseArray#indexOfKey(int)}.
 */
public static <E> ListIterator<E> iterateAt(SparseArray<E> array, int location) {
    return new SparseArrayIterator<E>(array, location);
}

private SparseArrayIterator(SparseArray<E> array, int location) {
    this.array = array;
    if (location < 0) {
        cursor = -1;
        cursorNowhere = true;
    } else if (location < array.size()) {
        cursor = location;
        cursorNowhere = false;
    } else {
        cursor = array.size() - 1;
        cursorNowhere = true;
    }
}

@Override
public boolean hasNext() {
    return cursor < array.size() - 1;
}

@Override
public boolean hasPrevious() {
    return cursorNowhere && cursor >= 0 || cursor > 0;
}

@Override
public int nextIndex() {
    if (hasNext()) {
        return array.keyAt(cursor + 1);
    } else {
        throw new NoSuchElementException();
    }
}

@Override
public int previousIndex() {
    if (hasPrevious()) {
        if (cursorNowhere) {
            return array.keyAt(cursor);
        } else {
            return array.keyAt(cursor - 1);
        }
    } else {
        throw new NoSuchElementException();
    }
}

@Override
public E next() {
    if (hasNext()) {
        if (cursorNowhere) {
            cursorNowhere = false;
        }
        cursor++;
        return array.valueAt(cursor);
    } else {
        throw new NoSuchElementException();
    }
}

@Override
public E previous() {
    if (hasPrevious()) {
        if (cursorNowhere) {
            cursorNowhere = false;
        } else {
            cursor--;
        }
        return array.valueAt(cursor);
    } else {
        throw new NoSuchElementException();
    }
}

@Override
public void add(E object) {
    throw new UnsupportedOperationException();
}

@Override
public void remove() {
    if (!cursorNowhere) {
        array.remove(array.keyAt(cursor));
        cursorNowhere = true;
        cursor--;
    } else {
        throw new IllegalStateException();
    }
}

@Override
public void set(E object) {
    if (!cursorNowhere) {
        array.setValueAt(cursor, object);
    } else {
        throw new IllegalStateException();
    }
}
}

9
আইএমএইচও এটি কিছুটা বেশি ইঞ্জিনিয়ারিং বলে মনে হচ্ছে। এটি দুর্দান্ত
hrules6872

12

পাই হিসাবে সহজ। লুপটি সম্পাদন করার আগে আপনি অ্যারের আকার আনছেন তা নিশ্চিত করুন ।

for(int i = 0, arraySize= mySparseArray.size(); i < arraySize; i++) {
   Object obj = mySparseArray.get(/* int key = */ mySparseArray.keyAt(i));
}

আশাকরি এটা সাহায্য করবে.


11

যে কেহ Kotlin একটি SparseArray পুনরুক্তি উপর সততার দ্বারা পর্যন্ত সবচেয়ে সহজ উপায় ব্যবহার করছে, জন্য: ব্যবহারের Kotlin এক্সটেনশন Anko বা অ্যান্ড্রয়েড KTX ! (অ্যান্ড্রয়েড কেটিএক্স দেখানোর জন্য কৃতিত্ব ইয়াজ্জেলোলোকে)

সহজভাবে ফোন করুন forEach { i, item -> }


হ্যাঁ, আপনি আসলে ঠিক বলেছেন। আমার খারাপ, আমি ট্যাগগুলি দেখেছিলাম এবং ভেবেছিলাম যে কোটলিন এখানে না থাকা উচিত। তবে এখন একটি দ্বিতীয় চিন্তা আছে যে এই উত্তরটি নিজেই কোটলিনের একটি ভাল রেফারেন্স। যদিও আনকো ব্যবহার না করে আমি android.github.io/android-ktx/core-ktx ব্যবহার করার পরামর্শ দিই (যদি আপনি দয়া করে আপনার উত্তরটি সম্পাদন করতে পারেন এবং অ্যান্ড্রয়েড-কেটিএক্স যোগ করতে পারেন তবে আমি এটি উত্সাহিত করব)
ইয়াজাজেলো

পছন্দ করেছেন
0101100101

7

SparseArrayউপরের লুপিং ব্যবহার থেকে সমস্ত উপাদান অপসারণ করার জন্য বাড়ে Exception

এটি এড়াতে SparseArrayসাধারণ লুপগুলি ব্যবহার থেকে সমস্ত উপাদান অপসারণ করতে নীচের কোডটি অনুসরণ করুন

private void getValues(){      
    for(int i=0; i<sparseArray.size(); i++){
          int key = sparseArray.keyAt(i);
          Log.d("Element at "+key, " is "+sparseArray.get(key));
          sparseArray.remove(key);
          i=-1;
    }
}

2
আমি = -1; শেষে কিছুই করে না। এছাড়াও একটি পদ্ধতি বলা হয় .clear()যা অনুকূল করা উচিত।
পল ওয়ালটাসেক

আপনি কেন কিছুক্ষণ () এর পরিবর্তে () লুপের জন্য ব্যবহার করবেন? আপনি যা করছেন তা লুপিংয়ের কোনও অর্থ নেই
ফিল এ

আমি ধরে নিলাম স্যাকুরিজ i-=1;এখন হারিয়ে যাওয়া উপাদানটির জন্য অ্যাকাউন্টে লিখতে চেয়েছিল । কিন্তু এটা লুপ রূপে ফিরিয়ে নিয়ে যেতে ভালো: for(int i=sparseArray.size()-1; i>=0; i++){...; অথবাwhile (sparseArray.size()>0) { int key=sparseArray.keyAt(0);...
ths

"উপরের লুপিং" এর মতো উল্লেখগুলি মোটেই কোনও অর্থ দেয় না।
অবিশ্বাস্য জানুয়ারি

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

5

এখানে সহজ Iterator<T>এবং Iterable<T>বাস্তবায়ন এর জন্য SparseArray<T>:

public class SparseArrayIterator<T> implements Iterator<T> {
    private final SparseArray<T> array;
    private int index;

    public SparseArrayIterator(SparseArray<T> array) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return array.size() > index;
    }

    @Override
    public T next() {
        return array.valueAt(index++);
    }

    @Override
    public void remove() {
        array.removeAt(index);
    }

}

public class SparseArrayIterable<T> implements Iterable<T> {
    private final SparseArray<T> sparseArray;

    public SparseArrayIterable(SparseArray<T> sparseArray) {
        this.sparseArray = sparseArray;
    }

    @Override
    public Iterator<T> iterator() {
        return new SparseArrayIterator<>(sparseArray);
    }
}

আপনি যদি কেবল একটি মান নয় তবে একটি কীও পুনরুক্ত করতে চান তবে:

public class SparseKeyValue<T> {
    private final int key;
    private final T value;

    public SparseKeyValue(int key, T value) {
        this.key = key;
        this.value = value;
    }

    public int getKey() {
        return key;
    }

    public T getValue() {
        return value;
    }
}

public class SparseArrayKeyValueIterator<T> implements Iterator<SparseKeyValue<T>> {
    private final SparseArray<T> array;
    private int index;

    public SparseArrayKeyValueIterator(SparseArray<T> array) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return array.size() > index;
    }

    @Override
    public SparseKeyValue<T> next() {
        SparseKeyValue<T> keyValue = new SparseKeyValue<>(array.keyAt(index), array.valueAt(index));
        index++;
        return keyValue;
    }

    @Override
    public void remove() {
        array.removeAt(index);
    }

}

public class SparseArrayKeyValueIterable<T> implements Iterable<SparseKeyValue<T>> {
    private final SparseArray<T> sparseArray;

    public SparseArrayKeyValueIterable(SparseArray<T> sparseArray) {
        this.sparseArray = sparseArray;
    }

    @Override
    public Iterator<SparseKeyValue<T>> iterator() {
        return new SparseArrayKeyValueIterator<T>(sparseArray);
    }
}

ফিরে আসা Iterable<T>এবং ইউটিলিটি পদ্ধতিগুলি তৈরি করতে এটি দরকারী Iterable<SparseKeyValue<T>>:

public abstract class SparseArrayUtils {
    public static <T> Iterable<SparseKeyValue<T>> keyValueIterable(SparseArray<T> sparseArray) {
        return new SparseArrayKeyValueIterable<>(sparseArray);
    }

    public static <T> Iterable<T> iterable(SparseArray<T> sparseArray) {
        return new SparseArrayIterable<>(sparseArray);
    }
}

এখন আপনি পুনরাবৃত্তি করতে পারেন SparseArray<T>:

SparseArray<String> a = ...;

for (String s: SparseArrayUtils.iterable(a)) {
   // ...
}

for (SparseKeyValue<String> s: SparseArrayUtils.keyValueIterable(a)) {
  // ...
}

4

আপনি যদি কোটলিন ব্যবহার করেন, আপনি যেমন এক্সটেনশন ফাংশনগুলি ব্যবহার করতে পারেন, উদাহরণস্বরূপ:

fun <T> LongSparseArray<T>.valuesIterator(): Iterator<T> {
    val nSize = this.size()
    return object : Iterator<T> {
        var i = 0
        override fun hasNext(): Boolean = i < nSize
        override fun next(): T = valueAt(i++)
    }
}

fun <T> LongSparseArray<T>.keysIterator(): Iterator<Long> {
    val nSize = this.size()
    return object : Iterator<Long> {
        var i = 0
        override fun hasNext(): Boolean = i < nSize
        override fun next(): Long = keyAt(i++)
    }
}

fun <T> LongSparseArray<T>.entriesIterator(): Iterator<Pair<Long, T>> {
    val nSize = this.size()
    return object : Iterator<Pair<Long, T>> {
        var i = 0
        override fun hasNext(): Boolean = i < nSize
        override fun next() = Pair(keyAt(i), valueAt(i++))
    }
}

আপনি যদি চান তবে একটি তালিকায় রূপান্তর করতেও পারেন। উদাহরণ:

sparseArray.keysIterator().asSequence().toList()

আমি মনে করি এটি নিজেরাই (পুনরুক্তিতে নয়) ব্যবহার removeকরে আইটেমগুলি মুছে ফেলা নিরাপদ হতে পারে LongSparseArrayকারণ এটি আরোহী ক্রমে রয়েছে।


সম্পাদনা করুন: মনে হচ্ছে ব্যবহার করা এমনকি একটি সহজ উপায়, সংগ্রহ-ktx (উদাহরণস্বরূপ এখানে )। এটি আমি যা লিখেছি তার সাথে খুব মিলিয়ে বাস্তবায়িত হয়েছে।

গ্রেডলের জন্য এটির প্রয়োজন:

implementation 'androidx.core:core-ktx:#'
implementation 'androidx.collection:collection-ktx:#'

লংস্পার্সআরয়ের ব্যবহার এখানে:

    val sparse= LongSparseArray<String>()
    for (key in sparse.keyIterator()) {
    }
    for (value in sparse.valueIterator()) {
    }
    sparse.forEach { key, value -> 
    }

আর যে জাভা ব্যবহারের জন্য, আপনি ব্যবহার করতে পারেন LongSparseArrayKt.keyIterator, LongSparseArrayKt.valueIteratorএবং LongSparseArrayKt.forEach, উদাহরণস্বরূপ। অন্যান্য ক্ষেত্রে একই।


-5

উত্তরটি না কারণ এটি সরবরাহ SparseArrayকরে না। যেমনটি pstবলা যায়, এই জিনিসটি কোনও ইন্টারফেস সরবরাহ করে না।

আপনি 0 - size()যে মানগুলি থেকে ফিরে যেতে পারেন এবং এড়িয়ে যেতে পারেন null, তবে এটি প্রায়।

আমি আমার মন্তব্যে যেমন বলেছি, আপনার যদি পুনরুক্তি করতে হয় তবে এটির Mapপরিবর্তে একটি ব্যবহার করুন SparseArray। উদাহরণস্বরূপ, একটি ব্যবহার করুন TreeMapযা কী দ্বারা ক্রমে পুনরাবৃত্তি হয়।

TreeMap<Integer, MyType>

-6

গৃহীত উত্তরের কিছু গর্ত রয়েছে। স্পার্সআরারের সৌন্দর্য হ'ল এটি অশ্লীলতার ফাঁকে ফাঁকে অনুমতি দেয়। সুতরাং, আমরা একটি স্পার্সআরেতে এর মতো দুটি মানচিত্র রাখতে পারি ...

(0,true)
(250,true)

লক্ষ্য করুন এখানে আকারটি 2 হবে we

for(int i = 0; i < sparseArray.size(); i++) {
   int key = sparseArray.keyAt(i);
   // get the object by the key.
   Object obj = sparseArray.get(key);
}

এটি করার সর্বোত্তম উপায় হ'ল আপনার ডেটা সেটের আকারের উপরে পুনরাবৃত্তি করা, তারপরে অ্যারেতে () দিয়ে সেই অশ্লীলতাগুলি পরীক্ষা করুন। এখানে অ্যাডাপ্টারের একটি উদাহরণ রয়েছে যেখানে আমি ব্যাচকে আইটেমগুলি মোছার অনুমতি দিচ্ছি।

for (int index = 0; index < mAdapter.getItemCount(); index++) {
     if (toDelete.get(index) == true) {
        long idOfItemToDelete = (allItems.get(index).getId());
        mDbManager.markItemForDeletion(idOfItemToDelete);
        }
    }

আমি মনে করি আদর্শভাবে স্পার্সআরে পরিবারে একটি getKeys () পদ্ধতি থাকবে তবে হায় আফসোস এটি হয় না।


4
আপনি ভুল - keyAtপদ্ধতিটি নবম কীটির মান দেয় (আপনার উদাহরণে keyAt(1)ফিরে আসবে 250), এতে বিভ্রান্ত হওয়ার দরকার নেই getযা কী দ্বারা রেফারেন্সকৃত উপাদানটির মান দেয়।
ইবারবব

আপনার মন্তব্যে 'এটি' কী তা আমি নিশ্চিত নই। আপনি কি স্বীকার করছেন যে আপনার উত্তরটি ভুল, বা আপনি বলছেন যে আমার মন্তব্যটি ভুল? তাহলে আধুনিক দয়া করে চেক করুন developer.android.com/reference/android/util/...
Eborbob

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