ইমটুটেবলজেএস দিয়ে তালিকার অভ্যন্তরে কীভাবে উপাদান আপডেট করবেন?


129

অফিসিয়াল ডক্স যা বলেছিল তা এখানে

updateIn(keyPath: Array<any>, updater: (value: any) => any): List<T>
updateIn(keyPath: Array<any>, notSetValue: any, updater: (value: any) => any): List<T>
updateIn(keyPath: Iterable<any, any>, updater: (value: any) => any): List<T>
updateIn(keyPath: Iterable<any, any>, notSetValue: any, updater: (value: any) => any): List<T>

সাধারণ ওয়েব বিকাশকারী (কার্যকরী প্রোগ্রামার নয়) এটি বোঝার কোনও উপায় নেই!

আমার কাছে বেশ সহজ (অ-কার্যকরী পদ্ধতির জন্য) কেস রয়েছে।

var arr = [];
arr.push({id: 1, name: "first", count: 2});
arr.push({id: 2, name: "second", count: 1});
arr.push({id: 3, name: "third", count: 2});
arr.push({id: 4, name: "fourth", count: 1});
var list = Immutable.List.of(arr);

listযেখানে তৃতীয় নামের এলিমেন্টটির গণনা 4 তে সেট করা আছে আমি কীভাবে আপডেট করব ?


43
এটি দেখতে কেমন তা আমি জানি না, তবে ডকুমেন্টেশনটি হ'ল ভয়াবহ ফেসবুক.
github.io/immutable-js/docs/#/List/update

71
ডকুমেন্টেশন এ খননের জন্য গুরুতর আপভোট। যদি সেই বাক্য গঠনটির লক্ষ্যটি হয় আমাকে বোবা / অপর্যাপ্ত অনুভব করা, সুনির্দিষ্ট সাফল্য। তবে লক্ষ্যটি যদি তা বোঝানো যায় যে অপরিবর্তনীয় কীভাবে কাজ করে, ভাল ...
ওয়ান

9
আমার একমত হতে হবে, আমি অপরিবর্তনীয় ডকুমেন্টেশনটি খুঁজে পাই .js গুরুতর হতাশার জন্য। এর জন্য গৃহীত সমাধানটি এমন একটি পদ্ধতি ফাইন্ড ইন্ডেক্স () ব্যবহার করে যা আমি এমনকি দস্তাবেজে দেখতে পাই না।
রিচার্ডফোরেস্টার

3
আমি বরং তারা প্রতিটি জিনিস জন্য এই জিনিস পরিবর্তে একটি উদাহরণ দিতে চাই।
রেডগিয়ান্ট

4
একমত। ডকুমেন্টেশন অবশ্যই কোনও বুদ্বুদে কোনও বিজ্ঞানী লিখেছেন, এমন কোনও ব্যক্তি দ্বারা নয় যা কিছু সাধারণ উদাহরণ দেখাতে চায়। ডকুমেন্টেশন কিছু ডকুমেন্টেশন প্রয়োজন। উদাহরণস্বরূপ, আমি আন্ডারস্কোর ডকুমেন্টেশন পছন্দ করি, ব্যবহারিক উদাহরণগুলি দেখতে আরও সহজ।
ReduxDJ

উত্তর:


119

সবচেয়ে উপযুক্ত ক্ষেত্রে হ'ল উভয় findIndexএবং updateপদ্ধতি ব্যবহার করা ।

list = list.update(
  list.findIndex(function(item) { 
    return item.get("name") === "third"; 
  }), function(item) {
    return item.set("count", 4);
  }
); 

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


1
আপনার যদি সদৃশ নাম প্রয়োজন হয়, মাল্টি ম্যাপ ব্যবহার করুন - বা মান হিসাবে টিপলস সহ মানচিত্র।
বার্গি

5
নাম হিসাবে "তিন" দিয়ে কোনও উপাদান না থাকলে এই অজান্তেই তালিকার শেষ উপাদানটি আপডেট করবে না? সেক্ষেত্রে ফাইন্ড ইন্ডেক্স () ফেরত -1 আসবে, যা আপডেট () শেষ উপাদানটির সূচক হিসাবে ব্যাখ্যা করবে।
স্যাম স্টোরি

1
না, -1 শেষ উপাদান নয়
ভিটালি কর্সাকভ

9
@ সাম স্টোরি ঠিক আছে। দস্তাবেজগুলি থেকে: "সূচকটি একটি নেতিবাচক সংখ্যা হতে পারে যা সূচকের শেষে থেকে সূচকগুলি ফিরে আসে v v.update (-1) তালিকার শেষ আইটেমটি আপডেট করে।" facebook.github.io/immutable-js/docs/#/List/update
গ্যাব্রিয়েল ফেরাজ

1
আমি আইটেম.সেট কল করতে পারিনি কারণ আমার পক্ষে আইটেমটি অপরিবর্তনীয় টাইপ ছিল না, আমাকে প্রথমে আইটেমটি মানচিত্র করতে হবে, কল সেট করতে হবে এবং তারপরে এটিকে আবার বস্তুতে রূপান্তর করতে হবে। সুতরাং এই উদাহরণস্বরূপ, ফাংশন (আইটেম) {মানচিত্র (আইটেম) .set ("গণনা", 4)। টোবজেক্ট (); }
সাইকেলে

36

.SetIn () এর মাধ্যমে আপনিও এটি করতে পারেন:

let obj = fromJS({
  elem: [
    {id: 1, name: "first", count: 2},
    {id: 2, name: "second", count: 1},
    {id: 3, name: "third", count: 2},
    {id: 4, name: "fourth", count: 1}
  ]
});

obj = obj.setIn(['elem', 3, 'count'], 4);

আমরা যদি প্রবেশের সূচিটি না জানি তবে আমরা আপডেট করতে চাই। .FindIndex () ব্যবহার করে এটি সন্ধান করা বেশ সহজ :

const indexOfListToUpdate = obj.get('elem').findIndex(listItem => {
  return listItem.get('name') === 'third';
});
obj = obj.setIn(['elem', indexOfListingToUpdate, 'count'], 4);

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


1
আপনি { }ভিতরে অনুপস্থিত fromJS( ), ধনুর্বন্ধনী ছাড়া এটি বৈধ জেএস নয় isn't
অ্যান্ডি

1
আমি প্রত্যাবর্তিত বস্তুকে 'আরর' বলব না কারণ এটি একটি বস্তু। কেবল অ্যারলিলেম একটি অ্যারে
ও।

21
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)

ব্যাখ্যা

ইমট্যটেবল.জেএস সংগ্রহগুলি আপডেট করা সর্বদা আসল অপরিবর্তিত রেখে col সংকলনের নতুন সংস্করণ ফিরিয়ে দেয়। সে কারণে আমরা জাভাস্ক্রিপ্টের list[2].count = 4মিউটেশন সিনট্যাক্স ব্যবহার করতে পারি না । পরিবর্তে আমাদের জাভা সংগ্রহের ক্লাসগুলির মতোই পদ্ধতিগুলি কল করতে হবে।

আসুন একটি সহজ উদাহরণ দিয়ে শুরু করা যাক: কেবলমাত্র একটি তালিকার গণনা।

var arr = [];
arr.push(2);
arr.push(1);
arr.push(2);
arr.push(1);
var counts = Immutable.List.of(arr);

এখন যদি আমরা 3 য় আইটেম আপডেট করতে চেয়েছিলেন, একটি প্লেইন জাতীয় অ্যারের অনুযায়ী প্রদর্শিত হবে: counts[2] = 4। যেহেতু আমরা মিউটেশনটি ব্যবহার করতে পারি না, এবং পরিবর্তে আমরা ব্যবহার করতে পারি একটি পদ্ধতি কল করা দরকার: counts.set(2, 4)- এর অর্থ 4সূচকে মান নির্ধারণ করে 2

গভীর আপডেট

আপনি যে উদাহরণ দিয়েছেন তাতে নেস্টেড ডেটা রয়েছে। আমরা কেবল set()প্রাথমিক সংগ্রহটি ব্যবহার করতে পারি না ।

ইমট্যটেবল.জেএস সংগ্রহের একটি পদ্ধতি রয়েছে যার নাম "ইন" দিয়ে শেষ হয় যা আপনাকে নেস্টেট সেটে আরও গভীর পরিবর্তন আনতে দেয়। সর্বাধিক সাধারণ আপডেটিং পদ্ধতিগুলির সাথে সম্পর্কিত "ইন" পদ্ধতি রয়েছে। উদাহরণস্বরূপ setআছে setIn। প্রথম যুক্তি হিসাবে কোনও সূচক বা কোনও কীকে গ্রহণ করার পরিবর্তে, এই "ইন" পদ্ধতিগুলি একটি "মূল পথ" গ্রহণ করে। মূল পথটি সূচক বা কীগুলির একটি অ্যারে যা আপনার আপডেট করতে চান এমন মান কীভাবে পাবেন তা চিত্রিত করে।

আপনার উদাহরণস্বরূপ, আপনি সূচী 2 তে তালিকার আইটেমটি আপডেট করতে চেয়েছিলেন এবং তারপরে সেই আইটেমের মধ্যে কী "গণনা" তে মান। তাই মূল পথ হবে [2, "count"]setInপদ্ধতির দ্বিতীয় প্যারামিটারটি ঠিক ঠিক এর মতোই কাজ করে set, এটি সেখানে আমরা নতুন মান রাখতে চাই, সুতরাং:

list = list.setIn([2, "count"], 4)

সঠিক কী পথটি সন্ধান করা হচ্ছে

আরও এক ধাপ এগিয়ে, আপনি আসলে বলেছিলেন যে আপনি যে আইটেমটি "থ্রি" নামের আইটেমটি আপডেট করতে চান যা কেবল ২ য় আইটেমের চেয়ে আলাদা। উদাহরণস্বরূপ, সম্ভবত আপনার তালিকাটি বাছাই করা হয়নি, বা সম্ভবত "দু" নামের আইটেমটি আগে সরিয়ে দেওয়া হয়েছে? তার মানে প্রথমে আমাদের নিশ্চিত করা দরকার যে আমরা আসলে সঠিক কীটি জানি! এর জন্য আমরা findIndex()পদ্ধতিটি ব্যবহার করতে পারি (যা যাইহোক, অ্যারে # ফাইন্ড ইন্ডেক্সের মতো প্রায় কাজ করে )।

একবার আমরা তালিকায় সূচিটি পেয়েছি যার মধ্যে আমরা আপডেট করতে চাই এমন আইটেমটি রয়েছে, আমরা যে মানটি আপডেট করতে চাই তার মূল পথটি সরবরাহ করতে পারি:

var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)

এনবি: SetবনামUpdate

মূল প্রশ্নটি সেট পদ্ধতির পরিবর্তে আপডেট পদ্ধতিগুলি উল্লেখ করে। আমি সেই ফাংশনটিতে দ্বিতীয় যুক্তিটি ব্যাখ্যা করব (ডাকা updater), যেহেতু এটির থেকে আলাদা set()। যদিও দ্বিতীয় আর্গুমেন্টটি set()আমরা চাই নতুন মান, তবে দ্বিতীয় আর্গুমেন্টটি update()এমন একটি ফাংশন যা পূর্ববর্তী মানটি গ্রহণ করে এবং আমরা চাইলে নতুন মানটি ফিরিয়ে দেয়। তারপরে, updateIn()"ইন" বৈকল্পিকতা update()যা কোনও মূল পথ গ্রহণ করে।

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

var index = list.findIndex(item => item.name === "three")
list = list.updateIn([index, "count"], value => value + 1)

19

অফিসিয়াল ডক্স যা বলেছে তা এখানে… updateIn

আপনার দরকার নেই updateIn, যা কেবল নেস্টেড স্ট্রাকচারের জন্য। আপনি সেই updateপদ্ধতিটি সন্ধান করছেন , যার একটি আরও সহজ স্বাক্ষর এবং ডকুমেন্টেশন রয়েছে:

বিদ্যমান মান সহ কলিং আপডেটেটরের রিটার্ন মান সহ সূচকে আপডেট হওয়া মান সহ একটি নতুন তালিকা প্রদান করে, বা সূচি সেট না করা থাকলে সেটওয়্যালু নয়।

update(index: number, updater: (value: T) => T): List<T>
update(index: number, notSetValue: T, updater: (value: T) => T): List<T>

যা Map::updateদস্তাবেজের পরামর্শ অনুসারে " সমান:list.set(index, updater(list.get(index, notSetValue))) " "

যেখানে "তৃতীয়" নামের উপাদান রয়েছে

তালিকাগুলি কীভাবে কাজ করে তা নয়। আপনি যে উপাদানটি আপডেট করতে চান তার সূচি আপনাকে জানতে হবে বা আপনাকে এটি অনুসন্ধান করতে হবে।

যেখানে তৃতীয় নামের এলিমেন্টটির সংখ্যা 4 তে নির্ধারণ করা আছে সেখানে আমি কীভাবে তালিকা আপডেট করতে পারি?

এটি করা উচিত:

list = list.update(2, function(v) {
    return {id: v.id, name: v.name, count: 4};
});

14
না, আপনার ডেটা স্ট্রাকচারের পছন্দটি ব্যবসায়ের যুক্তি পূরণ করে না :-) আপনি যদি তাদের নাম দ্বারা উপাদানগুলিতে অ্যাক্সেস করতে চান তবে আপনার তালিকার পরিবর্তে একটি মানচিত্র ব্যবহার করা উচিত।
বার্গি 13

1
@ বারগি, সত্যি? সুতরাং, যদি আমার কাছে কোনও ক্লাসের শিক্ষার্থীদের একটি তালিকা থাকে এবং আমি এই শিক্ষার্থীর ডেটাতে সিআরইউডি অপারেশন করতে চাই, তবে একটি Mapওভার এ ব্যবহার Listকরে আপনার পরামর্শ দেওয়ার উপায়টি কী? বা আপনি কি কেবল বলেছেন যে ওপি বলেছিল "নাম অনুসারে আইটেম নির্বাচন করুন" এবং "আইডি দ্বারা আইটেম নির্বাচন করবেন না"?
ডেভিড গিলবার্টসন

2
@ ডেভিডগিলবার্টসন: সিআরইউডি? আমি একটি ডাটাবেসটি পরামর্শ দেব :-) তবে হ্যাঁ, কোনও আইডি-> শিক্ষার্থীর মানচিত্র তালিকার চেয়ে আরও উপযুক্ত মনে হচ্ছে, যদি না আপনি তাদের উপর অর্ডার পেয়ে থাকেন এবং সেগুলি সূচক অনুসারে নির্বাচন করতে চান।
বার্গি

1
@ বার্গি আমি অনুমান করি আমরা একমত হতে সম্মত হব না, আমি আইডি সহ জিনিসগুলির অ্যারে আকারে এপিআই থেকে প্রচুর পরিমাণে তথ্য ফিরে পাই, যেখানে আইডির মাধ্যমে আমাকে সেই জিনিসগুলি আপডেট করতে হবে। এটি একটি জেএস অ্যারে, এবং আমার মনে, অতএব অপরিবর্তনীয় জেএস তালিকা হওয়া উচিত।
ডেভিড গিলবার্টসন

1
@ ডেভিডগিলবারসন: আমি মনে করি যে এপিআইগুলি সেটগুলির জন্য জেএসওন অ্যারে নেয় - যা স্পষ্টতই বিনা অর্ডারযুক্ত।
বার্গি

12

.Map () ব্যবহার করুন

list = list.map(item => 
   item.get("name") === "third" ? item.set("count", 4) : item
);

var arr = [];
arr.push({id: 1, name: "first", count: 2});
arr.push({id: 2, name: "second", count: 1});
arr.push({id: 3, name: "third", count: 2});
arr.push({id: 4, name: "fourth", count: 1});
var list = Immutable.fromJS(arr);

var newList = list.map(function(item) {
    if(item.get("name") === "third") {
      return item.set("count", 4);
    } else {
      return item;
    }
});

console.log('newList', newList.toJS());

// More succinctly, using ES2015:
var newList2 = list.map(item => 
    item.get("name") === "third" ? item.set("count", 4) : item
);

console.log('newList2', newList2.toJS());
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>


1
তার জন্য ধন্যবাদ - এখানে অনেক ভয়াবহ সংশ্লেষিত উত্তর, আসল উত্তরটি "আপনি যদি একটি তালিকা পরিবর্তন করতে চান, মানচিত্র ব্যবহার করুন"। অবিচ্ছিন্ন পরিবর্তনযোগ্য ডেটা স্ট্রাকচারের এটিই পুরো বিষয়, আপনি সেগুলিকে "আপডেট" করেন না, আপনি এতে আপডেট হওয়া মানগুলি সহ একটি নতুন কাঠামো তৈরি করেন; এবং এটি করা সস্তা কারণ অশোধিত তালিকার উপাদানগুলি ভাগ করা আছে।
কর্নি

2

থোমাস্টস ওয়েবসাইট থেকে আমি এই পদ্ধতির সত্যই পছন্দ করি :

const book = fromJS({
  title: 'Harry Potter & The Goblet of Fire',
  isbn: '0439139600',
  series: 'Harry Potter',
  author: {
    firstName: 'J.K.',
    lastName: 'Rowling'
  },
  genres: [
    'Crime',
    'Fiction',
    'Adventure',
  ],
  storeListings: [
    {storeId: 'amazon', price: 7.95},
    {storeId: 'barnesnoble', price: 7.95},
    {storeId: 'biblio', price: 4.99},
    {storeId: 'bookdepository', price: 11.88},
  ]
});

const indexOfListingToUpdate = book.get('storeListings').findIndex(listing => {
  return listing.get('storeId') === 'amazon';
});

const updatedBookState = book.setIn(['storeListings', indexOfListingToUpdate, 'price'], 6.80);

return state.set('book', updatedBookState);

-2

আপনি ব্যবহার করতে পারেন map:

list = list.map((item) => { 
    return item.get("name") === "third" ? item.set("count", 4) : item; 
});

তবে এটি পুরো সংগ্রহে পুনরাবৃত্তি হবে।

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