একটি জাভাস্ক্রিপ্ট পুনরাবৃত্তিকে অ্যারেতে রূপান্তর করা


171

আমি জাভাস্ক্রিপ্ট ইসি 6 থেকে নতুন মানচিত্র অবজেক্টটি ব্যবহার করার চেষ্টা করছি , কারণ এটি ইতিমধ্যে সর্বশেষতম ফায়ারফক্স এবং ক্রোম সংস্করণগুলিতে সমর্থিত।

তবে আমি এটি "কার্যকরী" প্রোগ্রামিংয়ে খুব সীমাবদ্ধ দেখছি, কারণ এতে ক্লাসিক মানচিত্র, ফিল্টার ইত্যাদি পদ্ধতির অভাব রয়েছে যা একটি [key, value]জুটির সাথে সুন্দরভাবে কাজ করবে । এটি একটি forEach আছে কিন্তু এটি কলব্যাক ফলাফল দেয় না।

আমি তার রুপান্তর পারে map.entries()একটি সহজ এরে মধ্যে একটি MapIterator থেকে আমি তখন মান ব্যবহার করতে পারে .map, .filterকোন অতিরিক্ত হ্যাক সঙ্গে।

জাভাস্ক্রিপ্ট আইট্রেটারকে অ্যারে রূপান্তর করার জন্য কি কোনও "ভাল" উপায় আছে? অজগরতে এটি করা যেমন সহজ list(iterator)... তবে Array(m.entries())ইটেটেরের সাথে এটির প্রথম উপাদান হিসাবে কোনও অ্যারে ফিরিয়ে দিন !!!

সম্পাদনা

আমি উল্লেখ করতে ভুলে গিয়েছি যে আমি কোনও উত্তর খুঁজছি যা মানচিত্র যেখানে কাজ করে সেখানেই কাজ করে যার অর্থ কমপক্ষে ক্রোম এবং ফায়ারফক্স (অ্যারে.ফ্রোম ক্রোমে কাজ করে না)।

পুনশ্চ.

আমি জানি চমত্কার wu.js আছে তবে এটি ট্রেসারের উপর নির্ভরশীলতা আমাকে দূরে সরিয়ে দিয়েছে ...


উত্তর:


247

আপনি নতুন Array.fromফাংশনটির সন্ধান করছেন যা স্বেচ্ছাসেবীর পুনরাবৃত্তিকে অ্যারে উদাহরণগুলিতে রূপান্তর করে:

var arr = Array.from(map.entries());

এটি এখন এজ, এফএফ, ক্রোম এবং নোড 4+ এ সমর্থিত

অবশ্যই, এটা নির্ধারণ করতে মূল্য হতে পারে map, filterএবং সরাসরি পুনরুক্তিকারীর ইন্টারফেসে অনুরূপ পদ্ধতি, যাতে আপনি অ্যারে বণ্টন এড়াতে পারবেন। আপনি উচ্চতর অর্ডার ফাংশনগুলির পরিবর্তে জেনারেটর ফাংশনটিও ব্যবহার করতে চাইতে পারেন:

function* map(iterable) {
    var i = 0;
    for (var item of iterable)
        yield yourTransformation(item, i++);
}
function* filter(iterable) {
    var i = 0;
    for (var item of iterable)
        if (yourPredicate(item, i++))
             yield item;
}

আমি কলব্যাকটি জোড় (value, key)না করে (value, index)জোড়া পাবে বলে আশা করব ।
অদিত এম শাহ 25'15

3
@ অদিতএমশাহ: পুনরাবৃত্তির কী কী? অবশ্যই, আপনি যদি কোনও মানচিত্রটি পুনরাবৃত্তি করতে চান তবে আপনি সংজ্ঞা দিতে পারেনyourTransformation = function([key, value], index) { … }
বার্গি

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

1
@ স্টেফানো: আপনি এটিকে সহজেই শিম করতে পারেন…
বার্গি

1
@ ছদ্মবেশী আহ ঠিক আছে, নিশ্চিত যে এটি সত্য, তবে এটি ঠিক যা প্রশ্ন জিজ্ঞাসা করছে, আমার উত্তর নিয়ে কোনও সমস্যা নয়।
বার্গি

45

[...map.entries()] অথবা Array.from(map.entries())

এটি অত্যন্ত সহজ।

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


1
আপনার কাছে আরও কিছু যথেষ্ট পরিমাণে না থাকলে এটি সত্যই একটি মন্তব্য হওয়া উচিত। এছাড়াও, Array.fromইতিমধ্যে @ বার্গি দ্বারা কভার করা হয়েছে।
অদিত এম শাহ

2
এবং, যেমন আমি আমার মূল প্রশ্নে লিখেছিলাম, [iterator]কাজ করে না কারণ ক্রোমে এটি এতে একটি iteratorউপাদান দিয়ে একটি অ্যারে তৈরি করে, এবং [...map.entries()]ক্রোমে কোনও স্বীকৃত বাক্য গঠন নয়
স্টেফানো

2
@ স্টেফানো স্প্রেড অপারেটর এখন ক্রোমে সিনট্যাক্স গ্রহণ করেছে
ক্লেসুন

15

একটি রুপান্তর করার কোন প্রয়োজন নেই Mapএকটি মধ্যে Array। আপনি কেবল অবজেক্টগুলির জন্য তৈরি mapএবং filterফাংশন করতে পারেন Map:

function map(functor, object, self) {
    var result = new Map;

    object.forEach(function (value, key, object) {
        result.set(key, functor.call(this, value, key, object));
    }, self);

    return result;
}

function filter(predicate, object, self) {
    var result = new Map;

    object.forEach(function (value, key, object) {
        if (predicate.call(this, value, key, object)) result.set(key, value);
    }, self);

    return result;
}

উদাহরণস্বরূপ, আপনি !মানচিত্রের প্রতিটি প্রবেশের মানতে একটি ঠুং শব্দ (অর্থাত্ চরিত্র) যুক্ত করতে পারেন যার মূলটি আদিম।

var object = new Map;

object.set("", "empty string");
object.set(0,  "number zero");
object.set(object, "itself");

var result = map(appendBang, filter(primitive, object));

alert(result.get(""));     // empty string!
alert(result.get(0));      // number zero!
alert(result.get(object)); // undefined

function primitive(value, key) {
    return isPrimitive(key);
}

function appendBang(value) {
    return value + "!";
}

function isPrimitive(value) {
    var type = typeof value;
    return value === null ||
        type !== "object" &&
        type !== "function";
}
<script>
function map(functor, object, self) {
    var result = new Map;

    object.forEach(function (value, key, object) {
        result.set(key, functor.call(this, value, key, object));
    }, self || null);

    return result;
}

function filter(predicate, object, self) {
    var result = new Map;

    object.forEach(function (value, key, object) {
        if (predicate.call(this, value, key, object)) result.set(key, value);
    }, self || null);

    return result;
}
</script>

এছাড়াও আপনি যোগ করতে পারিনি mapএবং filterউপর পদ্ধতি Map.prototypeএটা ভাল পড়া করতে। যদিও এটি সাধারণত এখনো নেটিভ এগুলির নমুনা পরিবর্তন না করাই ভালো আমি বিশ্বাস করি যে একটি ব্যতিক্রম ক্ষেত্রে করা যেতে পারে mapএবং filterএর জন্য Map.prototype:

var object = new Map;

object.set("", "empty string");
object.set(0,  "number zero");
object.set(object, "itself");

var result = object.filter(primitive).map(appendBang);

alert(result.get(""));     // empty string!
alert(result.get(0));      // number zero!
alert(result.get(object)); // undefined

function primitive(value, key) {
    return isPrimitive(key);
}

function appendBang(value) {
    return value + "!";
}

function isPrimitive(value) {
    var type = typeof value;
    return value === null ||
        type !== "object" &&
        type !== "function";
}
<script>
Map.prototype.map = function (functor, self) {
    var result = new Map;

    this.forEach(function (value, key, object) {
        result.set(key, functor.call(this, value, key, object));
    }, self || null);

    return result;
};

Map.prototype.filter = function (predicate, self) {
    var result = new Map;

    this.forEach(function (value, key, object) {
        if (predicate.call(this, value, key, object)) result.set(key, value);
    }, self || null);

    return result;
};
</script>


সম্পাদনা: বার্গির উত্তরে তিনি সমস্ত পুনরাবৃত্তিযোগ্য বস্তুর জন্য জেনেরিক mapএবং filterজেনারেটর ফাংশন তৈরি করেছিলেন । এগুলি ব্যবহারের সুবিধাটি হ'ল যেহেতু তারা জেনারেটর ফাংশন, তাই তারা মধ্যবর্তী পুনরাবৃত্তিযোগ্য বস্তুগুলি বরাদ্দ করে না।

উদাহরণস্বরূপ, আমার mapএবং filterফাংশনগুলি উপরে বর্ণিত নতুন Mapঅবজেক্ট তৈরি করে। সুতরাং কলিং object.filter(primitive).map(appendBang)দুটি নতুন Mapবস্তু তৈরি করে:

var intermediate = object.filter(primitive);
var result = intermediate.map(appendBang);

মধ্যবর্তী পুনরাবৃত্তিযোগ্য বস্তু তৈরি ব্যয়বহুল। বার্গির জেনারেটর ফাংশনগুলি এই সমস্যার সমাধান করে। তারা মধ্যবর্তী বস্তু বরাদ্দ দেয় না তবে একজন পুনরাবৃত্তিকে তার মানগুলি পরের দিকে অলসভাবে খাওয়ানোর অনুমতি দেয়। এই ধরণের অপ্টিমাইজেশান কার্যকরী প্রোগ্রামিং ভাষাগুলিতে ফিউশন বা বন উজাড় হিসাবে পরিচিত এবং এটি প্রোগ্রামের কার্য সম্পাদনকে উল্লেখযোগ্যভাবে উন্নতি করতে পারে।

বার্গির জেনারেটর ফাংশনগুলির সাথে আমার একটাই সমস্যা হ'ল এগুলি Mapবস্তুর সাথে নির্দিষ্ট নয় । পরিবর্তে, তারা সমস্ত পুনরাবৃত্তিযোগ্য বস্তুর জন্য সাধারণীকরণ করা হয়। সুতরাং জোড়গুলির সাথে কলব্যাক ফাংশনগুলিকে কল করার পরিবর্তে (value, key)(যেমনটি আমি ম্যাপিংয়ের সময় আশা করব Map) এর পরিবর্তে এটি জোড়গুলির সাথে কলব্যাক ফাংশনগুলিকে কল করে (value, index)। অন্যথায়, এটি একটি দুর্দান্ত সমাধান এবং আমি যে সমাধানগুলি সরবরাহ করেছি তার মধ্যে এটি অবশ্যই ব্যবহারের পরামর্শ দেব।

সুতরাং এগুলি নির্দিষ্ট জেনারেটর ফাংশন যা আমি ম্যাপিং এবং Mapঅবজেক্টগুলি ফিল্টার করার জন্য ব্যবহার করব :

function * map(functor, entries, self) {
    var that = self || null;

    for (var entry of entries) {
        var key   = entry[0];
        var value = entry[1];

        yield [key, functor.call(that, value, key, entries)];
    }
}

function * filter(predicate, entries, self) {
    var that = self || null;

    for (var entry of entries) {
        var key    = entry[0];
        var value  = entry[1];

        if (predicate.call(that, value, key, entries)) yield [key, value];
    }
}

function toMap(entries) {
    var result = new Map;

    for (var entry of entries) {
        var key   = entry[0];
        var value = entry[1];

        result.set(key, value);
    }

    return result;
}

function toArray(entries) {
    var array = [];

    for (var entry of entries) {
        array.push(entry[1]);
    }

    return array;
}

সেগুলি নিম্নলিখিত হিসাবে ব্যবহার করা যেতে পারে:

var object = new Map;

object.set("", "empty string");
object.set(0,  "number zero");
object.set(object, "itself");

var result = toMap(map(appendBang, filter(primitive, object.entries())));

alert(result.get(""));     // empty string!
alert(result.get(0));      // number zero!
alert(result.get(object)); // undefined

var array  = toArray(map(appendBang, filter(primitive, object.entries())));

alert(JSON.stringify(array, null, 4));

function primitive(value, key) {
    return isPrimitive(key);
}

function appendBang(value) {
    return value + "!";
}

function isPrimitive(value) {
    var type = typeof value;
    return value === null ||
        type !== "object" &&
        type !== "function";
}
<script>
function * map(functor, entries, self) {
    var that = self || null;

    for (var entry of entries) {
        var key   = entry[0];
        var value = entry[1];

        yield [key, functor.call(that, value, key, entries)];
    }
}

function * filter(predicate, entries, self) {
    var that = self || null;

    for (var entry of entries) {
        var key    = entry[0];
        var value  = entry[1];

        if (predicate.call(that, value, key, entries)) yield [key, value];
    }
}

function toMap(entries) {
    var result = new Map;

    for (var entry of entries) {
        var key   = entry[0];
        var value = entry[1];

        result.set(key, value);
    }

    return result;
}

function toArray(entries) {
    var array = [];

    for (var entry of entries) {
        array.push(entry[1]);
    }

    return array;
}
</script>

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

var object = new Map;

object.set("", "empty string");
object.set(0,  "number zero");
object.set(object, "itself");

var result = new MapEntries(object).filter(primitive).map(appendBang).toMap();

alert(result.get(""));     // empty string!
alert(result.get(0));      // number zero!
alert(result.get(object)); // undefined

var array  = new MapEntries(object).filter(primitive).map(appendBang).toArray();

alert(JSON.stringify(array, null, 4));

function primitive(value, key) {
    return isPrimitive(key);
}

function appendBang(value) {
    return value + "!";
}

function isPrimitive(value) {
    var type = typeof value;
    return value === null ||
        type !== "object" &&
        type !== "function";
}
<script>
MapEntries.prototype = {
    constructor: MapEntries,
    map: function (functor, self) {
        return new MapEntries(map(functor, this.entries, self), true);
    },
    filter: function (predicate, self) {
        return new MapEntries(filter(predicate, this.entries, self), true);
    },
    toMap: function () {
        return toMap(this.entries);
    },
    toArray: function () {
        return toArray(this.entries);
    }
};

function MapEntries(map, entries) {
    this.entries = entries ? map : map.entries();
}

function * map(functor, entries, self) {
    var that = self || null;

    for (var entry of entries) {
        var key   = entry[0];
        var value = entry[1];

        yield [key, functor.call(that, value, key, entries)];
    }
}

function * filter(predicate, entries, self) {
    var that = self || null;

    for (var entry of entries) {
        var key    = entry[0];
        var value  = entry[1];

        if (predicate.call(that, value, key, entries)) yield [key, value];
    }
}

function toMap(entries) {
    var result = new Map;

    for (var entry of entries) {
        var key   = entry[0];
        var value = entry[1];

        result.set(key, value);
    }

    return result;
}

function toArray(entries) {
    var array = [];

    for (var entry of entries) {
        array.push(entry[1]);
    }

    return array;
}
</script>

আশা করি এইটি কাজ করবে.


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

1
@ স্টেফানো আমি জেনারেটরগুলি কীভাবে Mapবিশেষায়িত mapএবং filterফাংশনগুলি ব্যবহার করে অবজেক্টগুলি সঠিকভাবে রূপান্তর করতে ব্যবহার করতে পারি তা দেখানোর জন্য আমার উত্তরটি সম্পাদনা করেছি । বার্গির উত্তরটি সমস্ত পুনরাবৃত্ত বস্তুর জন্য জেনেরিক mapএবং filterফাংশনগুলির ব্যবহার প্রদর্শন করে যা Mapবস্তুর রূপান্তর করার জন্য ব্যবহার করা যায় না কারণ বস্তুর চাবিগুলি Mapহারিয়ে গেছে।
অদিত এম শাহ

বাহ, আমি আপনার সম্পাদনাটি সত্যিই পছন্দ করি। আমি এখানে আমার নিজের উত্তরটি লিখে শেষ করেছি: stackoverflow.com/a/28721418/422670 (এই প্রশ্নটি নকল হিসাবে বন্ধ করা হয়েছে বলে সেখানে যুক্ত করা হয়েছে) কারণ Array.fromক্রোমে কাজ হয় না (যখন মানচিত্র এবং পুনরাবৃত্তিকারীরা করেন!)। তবে আমি দেখতে পাচ্ছি যে পদ্ধতিটি খুব একই রকম এবং আপনি কেবল "টু অ্যারে" ফাংশনটি আপনার গুচ্ছটিতে যুক্ত করতে পারেন!
স্টেফানো

1
পছন্দ করেছেন কীভাবে কোনও toArrayফাংশন যুক্ত করতে হয় তা দেখানোর জন্য আমি আমার উত্তর সম্পাদনা করেছি ।
অদিত এম শাহ 25'15

7

2019 সালের একটি ছোট আপডেট:

এখন অ্যারে.ফ্রোম সর্বজনীনভাবে উপলব্ধ বলে মনে হয় এবং তদ্ব্যতীত, এটি দ্বিতীয় যুক্তির মানচিত্রফনও গ্রহণ করে , যা এটি একটি মধ্যবর্তী অ্যারে তৈরি করা থেকে বাধা দেয়। এটি মূলত: এর মতো দেখায়:

Array.from(myMap.entries(), entry => {...});

যেহেতু Array.fromইতিমধ্যে একটি উত্তর ইতিমধ্যে বিদ্যমান, তাই এই মন্তব্যে মন্তব্য করা বা উত্তরটি সম্পাদনের জন্য অনুরোধ করা আরও উপযুক্ত ... তবে ধন্যবাদ!
স্টেফানো

1

আপনি https://www.npmjs.com/package/itiriri এর মতো লাইব্রেরি ব্যবহার করতে পারেন যা পুনরাবৃত্তদের জন্য অ্যারে-জাতীয় পদ্ধতি প্রয়োগ করে:

import { query } from 'itiriri';

const map = new Map();
map.set(1, 'Alice');
map.set(2, 'Bob');

const result = query(map)
  .filter([k, v] => v.indexOf('A') >= 0)
  .map([k, v] => `k - ${v.toUpperCase()}`);

for (const r of result) {
  console.log(r); // prints: 1 - ALICE
}

এই লিবটি আশ্চর্যজনক দেখাচ্ছে এবং অনুপস্থিত জলপথটি পুনরাবৃত্তিগুলি @ ডিমাদেবাতিতে লাফিয়ে উঠতে - এটি লেখার জন্য অনেক ধন্যবাদ, আমি শীঘ্রই চেষ্টা করব :-)
অ্যাঞ্জেলস পিকুলাস

0

আপনি অ্যারের অ্যারে (কী এবং মান) পেতে পারেন :

[...this.state.selected.entries()]
/**
*(2) [Array(2), Array(2)]
*0: (2) [2, true]
*1: (2) [3, true]
*length: 2
*/

এবং তারপরে, আপনি সহজেই অভ্যন্তর থেকে মানগুলি পেতে পারেন, উদাহরণস্বরূপ মানচিত্র পুনরুক্তিযুক্ত কীগুলি।

[...this.state.selected[asd].entries()].map(e=>e[0])
//(2) [2, 3]

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