ES6 মানচিত্র একসাথে একত্রিত করার জন্য কি কোনও সহজ উপায় আছে (যেমন Object.assign
)? এবং যখন আমরা এটি করছি, ES6 সেটগুলি (যেমন Array.concat
) সম্পর্কে কী ?
for..of
কারণ key
যে কোনও ধরণের হতে পারে
ES6 মানচিত্র একসাথে একত্রিত করার জন্য কি কোনও সহজ উপায় আছে (যেমন Object.assign
)? এবং যখন আমরা এটি করছি, ES6 সেটগুলি (যেমন Array.concat
) সম্পর্কে কী ?
for..of
কারণ key
যে কোনও ধরণের হতে পারে
উত্তর:
সেট জন্য:
var merged = new Set([...set1, ...set2, ...set3])
মানচিত্রের জন্য:
var merged = new Map([...map1, ...map2, ...map3])
মনে রাখবেন যে একাধিক মানচিত্রে একই কী থাকলে, একত্রিত মানচিত্রের মানটি সেই কীটির সাথে সর্বশেষ মার্জিং মানচিত্রের মান হবে।
Map
: "রচয়িতা: new Map([iterable])
", " iterable
একটি অ্যারের বা অন্যান্য iterable বস্তুর যার উপাদান কী-মান জোড়া (2- উপাদান অ্যারেগুলির) হয়। প্রতিটি মান-মান জুড়ি নতুন মানচিত্রে যুক্ত করা হয়। - ঠিক রেফারেন্স হিসাবে।
Map
তাদের মেমরির খরচ এড়ানো যায়।
জেনারেটর ব্যবহার করে আমার সমাধানটি এখানে দেওয়া হয়েছে:
মানচিত্রের জন্য:
let map1 = new Map(), map2 = new Map();
map1.set('a', 'foo');
map1.set('b', 'bar');
map2.set('b', 'baz');
map2.set('c', 'bazz');
let map3 = new Map(function*() { yield* map1; yield* map2; }());
console.log(Array.from(map3)); // Result: [ [ 'a', 'foo' ], [ 'b', 'baz' ], [ 'c', 'bazz' ] ]
সেটগুলির জন্য:
let set1 = new Set(['foo', 'bar']), set2 = new Set(['bar', 'baz']);
let set3 = new Set(function*() { yield* set1; yield* set2; }());
console.log(Array.from(set3)); // Result: [ 'foo', 'bar', 'baz' ]
m2.forEach((k,v)=>m1.set(k,v))
যদি আপনি চান সহজ ব্রাউজার সমর্থনের
যে কারণে আমি বুঝতে পারি না, আপনি অন্তর্নির্মিত অপারেশন দিয়ে একটি সেট এর সামগ্রী সরাসরি অন্য সেটটিতে যুক্ত করতে পারবেন না। ইউনিয়ন, ছেদ করা, মার্জ করা ইত্যাদির মতো অপারেশনগুলি হ'ল সুন্দর বেসিক সেট অপারেশন, তবে অন্তর্নির্মিত নয়। ভাগ্যক্রমে, আপনি এগুলি নিজেরাই মোটামুটি সহজেই তৈরি করতে পারেন।
সুতরাং, একত্রীকরণ ক্রিয়াকলাপটি বাস্তবায়নের জন্য (এক সেটের সামগ্রীগুলিকে অন্য একটিতে বা একটি মানচিত্রে অন্য একত্রে মার্জ করা) আপনি একক .forEach()
লাইন দিয়ে এটি করতে পারেন :
var s = new Set([1,2,3]);
var t = new Set([4,5,6]);
t.forEach(s.add, s);
console.log(s); // 1,2,3,4,5,6
এবং, একটির জন্য Map
, আপনি এটি করতে পারেন:
var s = new Map([["key1", 1], ["key2", 2]]);
var t = new Map([["key3", 3], ["key4", 4]]);
t.forEach(function(value, key) {
s.set(key, value);
});
অথবা, ES6 সিনট্যাক্সে:
t.forEach((value, key) => s.set(key, value));
এফওয়াইআই, যদি আপনি কোনও বিল্ট-ইন Set
অবজেক্টের কোনও সাধারণ সাবক্লাস চান যাতে কোনও .merge()
পদ্ধতি থাকে তবে আপনি এটি ব্যবহার করতে পারেন:
// subclass of Set that adds new methods
// Except where otherwise noted, arguments to methods
// can be a Set, anything derived from it or an Array
// Any method that returns a new Set returns whatever class the this object is
// allowing SetEx to be subclassed and these methods will return that subclass
// For this to work properly, subclasses must not change behavior of SetEx methods
//
// Note that if the contructor for SetEx is passed one or more iterables,
// it will iterate them and add the individual elements of those iterables to the Set
// If you want a Set itself added to the Set, then use the .add() method
// which remains unchanged from the original Set object. This way you have
// a choice about how you want to add things and can do it either way.
class SetEx extends Set {
// create a new SetEx populated with the contents of one or more iterables
constructor(...iterables) {
super();
this.merge(...iterables);
}
// merge the items from one or more iterables into this set
merge(...iterables) {
for (let iterable of iterables) {
for (let item of iterable) {
this.add(item);
}
}
return this;
}
// return new SetEx object that is union of all sets passed in with the current set
union(...sets) {
let newSet = new this.constructor(...sets);
newSet.merge(this);
return newSet;
}
// return a new SetEx that contains the items that are in both sets
intersect(target) {
let newSet = new this.constructor();
for (let item of this) {
if (target.has(item)) {
newSet.add(item);
}
}
return newSet;
}
// return a new SetEx that contains the items that are in this set, but not in target
// target must be a Set (or something that supports .has(item) such as a Map)
diff(target) {
let newSet = new this.constructor();
for (let item of this) {
if (!target.has(item)) {
newSet.add(item);
}
}
return newSet;
}
// target can be either a Set or an Array
// return boolean which indicates if target set contains exactly same elements as this
// target elements are iterated and checked for this.has(item)
sameItems(target) {
let tsize;
if ("size" in target) {
tsize = target.size;
} else if ("length" in target) {
tsize = target.length;
} else {
throw new TypeError("target must be an iterable like a Set with .size or .length");
}
if (tsize !== this.size) {
return false;
}
for (let item of target) {
if (!this.has(item)) {
return false;
}
}
return true;
}
}
module.exports = SetEx;
এটি তার নিজের ফাইল setex.js এর মধ্যে থাকা যা আপনি তারপরে নোড.জেজে andুকে require()
বিল্ট-ইন সেটের জায়গায় ব্যবহার করতে পারবেন ।
new Set(s, t)
। কাজ করে। t
পরামিতি উপেক্ষা করা হয়। এছাড়াও, add
এটির প্যারামিটারের ধরনটি সনাক্ত করা এবং কোনও সেট যদি সেটের উপাদানগুলিকে যুক্ত করে তবে স্পষ্টত যুক্তিসঙ্গত আচরণ নয় কারণ সেটে কোনও সেট নিজেকে যুক্ত করার কোনও উপায় থাকবে না।
.add()
একটি সেট নেওয়ার পদ্ধতি হিসাবে , আমি আপনার বক্তব্যটি বুঝতে পারি। আমি কেবল .add()
সেট বা সংযোজনগুলির প্রয়োজনের আগে কখনও কখনও সেট ব্যবহার করে সেটগুলি একত্রিত করতে সক্ষম হওয়ার চেয়ে কম ব্যবহারের সন্ধান পেয়েছি, তবে আমার অনেকবার সেটগুলি মার্জ করার দরকার পড়েছিল। একটি ব্যবহারের তুলনায় অন্যটির ব্যবহারের মতামতের বিষয়।
n.forEach(m.add, m)
এটি মানচিত্রের জন্য কাজ করে না: - এটি কী / মান জোড়া উল্টায়!
Map.prototype.forEach()
এবং Map.prototype.set()
যুক্তিগুলি বিপরীত করেছে। কারও মতামত দেখে মনে হচ্ছে। এটি এক সাথে ব্যবহার করার চেষ্টা করার সময় আরও কোড জোর করে।
set
পরামিতি অর্ডার কী / মান জোড়া জন্য প্রাকৃতিক হয়, forEach
সঙ্গে সংযুক্ত করা হয় Array
গুলি forEach
(এবং ভালো জিনিস পদ্ধতি $.each
বা _.each
যে গনা বস্তু)।
সম্পাদনা করুন :
আমি অন্যান্য সমাধানগুলির বিপরীতে আমার মূল সমাধানটি বেঞ্চমার্ক করেছি এবং দেখতে পেয়েছি যে এটি অত্যন্ত অদক্ষ।
মানদণ্ডটি নিজেই খুব আকর্ষণীয় ( লিঙ্ক ) এটি 3 টি সমাধানের তুলনা করে (উচ্চতর ভাল):
- @ বিফ্রেড.ইটের সমাধান যা একের পর এক মান যোগ করে (14,955 অপ / সেকেন্ড)
- @ জেমস্লকের সমাধান, যা স্ব-চালিত জেনারেটর ব্যবহার করে (৫,০৯৯ অপ / সেকেন্ড)
- আমার নিজস্ব, যা হ্রাস এবং ছড়িয়ে পড়ে (3,434 অপ / সেকেন্ড)
আপনি দেখতে পাচ্ছেন, @ bfred.it এর সমাধানটি অবশ্যই বিজয়ী।
পারফরম্যান্স + অপ্রচলতা
এই বিষয়টি মনে রেখে, এখানে একটি সামান্য পরিবর্তিত সংস্করণ দেওয়া হয়েছে যা মূল সেটটিকে রূপান্তরিত করে না এবং তর্কযোগ্য সংখ্যক পুনরাবৃত্তিকে আর্গুমেন্ট হিসাবে একত্রিত করতে ব্যতীত:
function union(...iterables) { const set = new Set(); for (let iterable of iterables) { for (let item of iterable) { set.add(item); } } return set; }
ব্যবহার:
const a = new Set([1, 2, 3]); const b = new Set([1, 3, 5]); const c = new Set([4, 5, 6]); union(a,b,c) // {1, 2, 3, 4, 5, 6}
আমি অপারেটরটি ব্যবহার করে reduce
এবং spread
অপারেটরটিকে আরও একটি পদ্ধতির পরামর্শ দিতে চাই :
function union (sets) {
return sets.reduce((combined, list) => {
return new Set([...combined, ...list]);
}, new Set());
}
ব্যবহার:
const a = new Set([1, 2, 3]);
const b = new Set([1, 3, 5]);
const c = new Set([4, 5, 6]);
union([a, b, c]) // {1, 2, 3, 4, 5, 6}
টিপ:
rest
ইন্টারফেসটি কিছুটা সুন্দর করতে আমরা অপারেটরটি ব্যবহার করতে পারি :
function union (...sets) {
return sets.reduce((combined, list) => {
return new Set([...combined, ...list]);
}, new Set());
}
এখন, পরিবর্তে একটি ক্ষণস্থায়ী অ্যারের সেট, আমরা এর একটি অবাধ সংখ্যা প্রেরণ করতে পারেন আর্গুমেন্ট সেট:
union(a, b, c) // {1, 2, 3, 4, 5, 6}
forof
এবং add
এটি কেবল খুব অদক্ষ বলে মনে হয়। আমি সত্যিই addAll(iterable)
function union<T> (...iterables: Array<Set<T>>): Set<T> { const set = new Set<T>(); iterables.forEach(iterable => { iterable.forEach(item => set.add(item)) }) return set }
অনুমোদিত উত্তরটি দুর্দান্ত তবে এটি প্রতিবারই একটি নতুন সেট তৈরি করে।
আপনি যদি এর পরিবর্তে কোনও বিদ্যমান অবজেক্টটি রূপান্তর করতে চান তবে একটি সহায়ক ফাংশন ব্যবহার করুন।
function concatSets(set, ...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
set.add(item);
}
}
}
ব্যবহার:
const setA = new Set([1, 2, 3]);
const setB = new Set([4, 5, 6]);
const setC = new Set([7, 8, 9]);
concatSets(setA, setB, setC);
// setA will have items 1, 2, 3, 4, 5, 6, 7, 8, 9
function concatMaps(map, ...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
map.set(...item);
}
}
}
ব্যবহার:
const mapA = new Map().set('S', 1).set('P', 2);
const mapB = new Map().set('Q', 3).set('R', 4);
concatMaps(mapA, mapB);
// mapA will have items ['S', 1], ['P', 2], ['Q', 3], ['R', 4]
অ্যারে সেটগুলিতে সেটগুলি মার্জ করতে, আপনি এটি করতে পারেন
var Sets = [set1, set2, set3];
var merged = new Set([].concat(...Sets.map(set => Array.from(set))));
আমার কাছে এটি কিছুটা রহস্যজনক যে নিম্নলিখিতগুলি, যা সমমানের হওয়া উচিত, অন্তত বাবেলে ব্যর্থ হয়:
var merged = new Set([].concat(...Sets.map(Array.from)));
Array.from
অতিরিক্ত পরামিতি নেয়, দ্বিতীয়টি ম্যাপিংয়ের কাজ। Array.prototype.map
এর কলব্যাকটিতে তিনটি আর্গুমেন্ট পাস করে: (value, index, array)
সুতরাং এটি কার্যকরভাবে কল করছে Sets.map((set, index, array) => Array.from(set, index, array)
। স্পষ্টতই, index
এটি একটি নম্বর এবং কোনও ম্যাপিং ফাংশন নয় তাই এটি ব্যর্থ হয়।
এটা তোলে কোনো অর্থে দেখা যায় না ডাকতে new Set(...anArrayOrSet)
যখন একাধিক উপাদান যুক্ত করার (হয় একটি অ্যারের বা অন্য সেট থেকে) একটি বিদ্যমান সেটে ।
আমি এটি একটি reduce
ফাংশনে ব্যবহার করি এবং এটি কেবল সরল মূর্খ। আপনার কাছে ...array
স্প্রেড অপারেটর উপলভ্য থাকলেও , আপনার এটি এ ক্ষেত্রে ব্যবহার করা উচিত নয়, কারণ এটি প্রসেসর, মেমরি এবং সময় সংস্থানকে অপচয় করে।
// Add any Map or Set to another
function addAll(target, source) {
if (target instanceof Map) {
Array.from(source.entries()).forEach(it => target.set(it[0], it[1]))
} else if (target instanceof Set) {
source.forEach(it => target.add(it))
}
}
// Add any Map or Set to another
function addAll(target, source) {
if (target instanceof Map) {
Array.from(source.entries()).forEach(it => target.set(it[0], it[1]))
} else if (target instanceof Set) {
source.forEach(it => target.add(it))
}
}
const items1 = ['a', 'b', 'c']
const items2 = ['a', 'b', 'c', 'd']
const items3 = ['d', 'e']
let set
set = new Set(items1)
addAll(set, items2)
addAll(set, items3)
console.log('adding array to set', Array.from(set))
set = new Set(items1)
addAll(set, new Set(items2))
addAll(set, new Set(items3))
console.log('adding set to set', Array.from(set))
const map1 = [
['a', 1],
['b', 2],
['c', 3]
]
const map2 = [
['a', 1],
['b', 2],
['c', 3],
['d', 4]
]
const map3 = [
['d', 4],
['e', 5]
]
const map = new Map(map1)
addAll(map, new Map(map2))
addAll(map, new Map(map3))
console.log('adding map to map',
'keys', Array.from(map.keys()),
'values', Array.from(map.values()))
সেটগুলিকে অ্যারেতে রূপান্তর করুন, এগুলি সমতল করুন এবং শেষ পর্যন্ত নির্মাণকারী অদৃশ্য হয়ে যাবে।
const union = (...sets) => new Set(sets.map(s => [...s]).flat());
না, এগুলির জন্য কোনও বিল্টিন অপারেশন নেই তবে আপনি এগুলি সহজেই নিজের তৈরি করতে পারেন:
Map.prototype.assign = function(...maps) {
for (const m of maps)
for (const kv of m)
this.add(...kv);
return this;
};
Set.prototype.concat = function(...sets) {
const c = this.constructor;
let res = new (c[Symbol.species] || c)();
for (const set of [this, ...sets])
for (const v of set)
res.add(v);
return res;
};
const mergedMaps = (...maps) => {
const dataMap = new Map([])
for (const map of maps) {
for (const [key, value] of map) {
dataMap.set(key, value)
}
}
return dataMap
}
const map = mergedMaps(new Map([[1, false]]), new Map([['foo', 'bar']]), new Map([['lat', 1241.173512]]))
Array.from(map.keys()) // [1, 'foo', 'lat']
এগুলি একত্রিত করতে আপনি স্প্রেড সিনট্যাক্সটি ব্যবহার করতে পারেন :
const map1 = {a: 1, b: 2}
const map2 = {b: 1, c: 2, a: 5}
const mergedMap = {...a, ...b}
=> {a: 5, b: 1, c: 2}
মানচিত্রে মার্জ করুন
let merge = {...map1,...map2};