डार्ट में सूचकांक और मूल्य के साथ एक सूची के माध्यम से गणना या मानचित्र


99

डार्ट में आम के बराबर कोई भी:

enumerate(List) -> Iterator((index, value) => f)
or 
List.enumerate()  -> Iterator((index, value) => f)
or 
List.map() -> Iterator((index, value) => f)

ऐसा लगता है कि यह सबसे आसान तरीका है, लेकिन यह अभी भी अजीब लगता है कि यह कार्यक्षमता मौजूद नहीं है।

Iterable<int>.generate(list.length).forEach( (index) => {
  newList.add(list[index], index)
});

संपादित करें:

@ हेमंथ-राज की बदौलत मैं उस समाधान को पा सका था जिसकी मुझे तलाश थी। मैं इसे यहां किसी के लिए भी रखूंगा, जिसे कुछ ऐसा ही करने की जरूरत है।

List<Widget> _buildWidgets(List<Object> list) {
    return list
        .asMap()
        .map((index, value) =>
            MapEntry(index, _buildWidget(index, value)))
        .values
        .toList();
}

वैकल्पिक रूप से आप एक पुन: प्रयोज्य वापस करने के लिए एक तुल्यकालिक जनरेटर फ़ंक्शन बना सकते हैं

Iterable<MapEntry<int, T>> enumerate<T>(Iterable<T> items) sync* {
  int index = 0;
  for (T item in items) {
    yield MapEntry(index, item);
    index = index + 1;
  }
}

//and use it like this.
var list = enumerate([0,1,3]).map((entry) => Text("index: ${entry.key}, value: ${entry.value}"));

Map#forEach? यह वही है जो आप चाहते हैं?
pskink

यह एक सूची के माध्यम से गणना कर रहा है न कि नक्शा
डेविड रीस

नक्शा # forEach एक के माध्यम से enumerating है List? आपका मतलब क्या है? डॉक्स कहते हैं: "नक्शे के प्रत्येक कुंजी / मान युग्म पर लागू होता है। कॉलिंग f को मानचित्र से कुंजियों को जोड़ना या निकालना नहीं चाहिए।"
pskink

मुझे यह भी समझ में नहीं आ रहा है कि "इंड्यूएट या इंडेक्स और वैल्यू वाली सूची के माध्यम से मैप करें" का क्या मतलब है
गुंटर ज़ोचबॉयर

जवाबों:


152

एक asMapविधि है जो सूची को एक नक्शे में परिवर्तित करती है जहां चाबियाँ सूचकांक हैं और सूचकांक में तत्व हैं। कृपया यहां डॉक्स पर एक नज़र डालें ।

उदाहरण:

List _sample = ['a','b','c'];
_sample.asMap().forEach((index, value) => f);

उम्मीद है की यह मदद करेगा!


35

पुनरावृत्ति सूचकांक प्राप्त करने के लिए कोई अंतर्निहित फ़ंक्शन नहीं है।

अगर मेरी तरह आप Mapएक सरल सूचकांक के लिए ((डेटा संरचना) बनाने के विचार को पसंद नहीं करते हैं , तो आप जो चाहते हैं वह एक map(फ़ंक्शन) है जो आपको सूचकांक देता है। आइए इसे कहते हैं mapIndexed(जैसे कोटलिन में):

children: mapIndexed(
  list,
  (index, item) => Text("event_$index")
).toList();

का कार्यान्वयन mapIndexedसरल है:

Iterable<E> mapIndexed<E, T>(
    Iterable<T> items, E Function(int index, T item) f) sync* {
  var index = 0;

  for (final item in items) {
    yield f(index, item);
    index = index + 1;
  }
}

1
यह एक अच्छा जवाब है, लेकिन संभवतः एक सिंक्रोनस जनरेटर के रूप में बेहतर लिखा जाएगा
डेविड रीस

2
सुझाव के लिए @DavidRees thx! मैंने फ़ंक्शन का नाम भी बदल दियाmapIndexed
विवियन

1
यह शर्म की बात है कि डार्ट के पास ऐसा करने का आसान तरीका नहीं है। 30 साल का अजगर भी आसानी से ऐसा कर सकता है!
ओसमू

यह पता चला है कि .asMap().forEach()अनिवार्य रूप से इस के समान है - मेरा जवाब देखें।
टिम्मम

1
@Timmmm मुझे लगता है कि asMap()डेटा को पुनः प्राप्त करने के लिए अतिरिक्त लूप खर्च होंगे, इस प्रकार यह mapIndexed()ऊपर की तरह कुशल नहीं होगा ।
एंटिकैफ़र

18

@ हेमंत राज जवाब पर बिल्डिंग।

इसे वापस करने के लिए आप कर सकते हैं

List<String> _sample = ['a', 'b', 'c'];
_sample.asMap().values.toList(); 
//returns ['a', 'b', 'c'];

या यदि आपको एक मैपिंग फ़ंक्शन के लिए सूचकांक की आवश्यकता है, तो आप ऐसा कर सकते हैं:

_sample
.asMap()
.map((index, str) => MapEntry(index, str + index.toString()))
.values
.toList();
// returns ['a0', 'b1', 'c2']

16

डार्ट 2.7 के साथ शुरू, आप सहायक विधियों को लिखने extensionके Iterableबजाय की कार्यक्षमता को बढ़ाने के लिए उपयोग कर सकते हैं

extension ExtendedIterable<E> on Iterable<E> {
  /// Like Iterable<T>.map but callback have index as second argument
  Iterable<T> mapIndex<T>(T f(E e, int i)) {
    var i = 0;
    return this.map((e) => f(e, i++));
  }

  void forEachIndex(void f(E e, int i)) {
    var i = 0;
    this.forEach((e) => f(e, i++));
  }
}

उपयोग:

final inputs = ['a', 'b', 'c', 'd', 'e', 'f'];
final results = inputs
  .mapIndex((e, i) => 'item: $e, index: $i')
  .toList()
  .join('\n');

print(results);

// item: a, index: 0
// item: b, index: 1
// item: c, index: 2
// item: d, index: 3
// item: e, index: 4
// item: f, index: 5
inputs.forEachIndex((e, i) => print('item: $e, index: $i'));

// item: a, index: 0
// item: b, index: 1
// item: c, index: 2
// item: d, index: 3
// item: e, index: 4
// item: f, index: 5

2
यह सबसे अच्छा जवाब है, यह भी स्पंदन आइटम के साथ काम करता है जहां आप विजेट को न केवल स्ट्रिंग वापस कर सकते हैं।
स्टील

8

लुकास रेंग्गली के अधिक पैकेज में 'अनुक्रमित' सहित कई उपयोगी उपकरण शामिल हैं, जो वास्तव में आप चाहते हैं। डॉक्स से:

indexed(['a', 'b'], offset: 1)
  .map((each) => '${each.index}: ${each.value}')
  .join(', ');

(आप ऑफसेट तर्क को तब तक अनदेखा कर सकते हैं जब तक कि आपके पास एक स्मालटाक पृष्ठभूमि नहीं है :-)


7

मैंने शुरू में सोचा था कि ['one', 'two', 'three'].asMap().forEach((index, value) { ... });यह वास्तव में अक्षम है क्योंकि ऐसा लगता है कि यह सूची को मानचित्र में परिवर्तित कर रहा है। वास्तव में यह नहीं है - प्रलेखन का कहना है कि यह सूची का एक अपरिवर्तनीय दृश्य बनाता है । मैंने dart2jsइस कोड के साथ डबल चेक किया :

void main() {
  final foo = ['one', 'two', 'three'];
  foo.asMap().forEach((idx, val) {
    print('$idx: $val');
  });
}

यह बहुत कोड उत्पन्न करता है ! लेकिन यह है:

  main: function() {
    var foo = H.setRuntimeTypeInfo(["one", "two", "three"], ...);
    new H.ListMapView(foo, ...).forEach$1(0, new F.main_closure());
  },

  H.ListMapView.prototype = {
    forEach$1: function(_, f) {
      var t1, $length, t2, i;
      ...
      t1 = this._values;
      $length = t1.length;
      for (t2 = $length, i = 0; i < $length; ++i) {
        if (i >= t2)
          return H.ioore(t1, i);
        f.call$2(i, t1[i]);
        t2 = t1.length;
        if ($length !== t2)
          throw H.wrapException(P.ConcurrentModificationError$(t1));
      }
    },
    ...
  },

  F.main_closure.prototype = {
    call$2: function(idx, val) {
      ...
      H.printString("" + idx + ": " + H.S(val));
    },
    $signature: 1
  };

तो यह कुशल करने के लिए पर्याप्त स्मार्ट है! बहुत चालाक है।

बेशक आप सिर्फ लूप के लिए एक सामान्य का उपयोग कर सकते हैं:

for (var index = 0; index < values.length; ++index) {
  final value = values[index];

4

सुविधा के लिए आप इस एक्सटेंशन विधि का उपयोग कर सकते हैं।

extension CollectionUtil<T> on Iterable<T>  {

  Iterable<E> mapIndexed<E, T>(E Function(int index, T item) transform) sync* {
    var index = 0;

    for (final item in this) {
      yield transform(index, item as T);
      index++;
    }
  }
}

3

पहले मानचित्र को सूची में बदलने के लिए asMap का उपयोग करें । तत्व का सूचकांक कुंजी है। तत्व मान बन जाता है। कुंजी का उपयोग करने के लिए और आप जो भी चाहते हैं उसका मूल्य दर्ज करने के लिए प्रविष्टियों का उपयोग करें ।

List rawList = ["a", "b", "c"];
List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList();
print(argList);

आउटपुट:

[0:a, 1:b, 2:c]

0

आप Iterable.generateकारखाने का उपयोग कर सकते हैं । निम्नलिखित कोड एक Iterableइंडेक्स और मान का उपयोग करके मैप करेगा ।

extension IterableMapIndex<T> on Iterable<T> {
  Iterable<E> mapIndexed<E>(E f(int index, T t)) {
    return Iterable.generate(this.length, (index)=>f(index, elementAt(index)));
  }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.