মিলিত আইটেমটি প্রতিস্থাপন করার জন্য লডাসে কোনও ফাংশন রয়েছে কি?


134

আমি ভাবছি কোনও জাভাস্ক্রিপ্ট সংগ্রহে কোনও আইটেম প্রতিস্থাপনের জন্য লোডাশের কোনও সহজ পদ্ধতি আছে কিনা? (সম্ভাব্য সদৃশ কিন্তু আমি উত্তরটি বুঝতে পারি নি :)

আমি তাদের ডকুমেন্টেশনের দিকে তাকিয়েছিলাম কিন্তু কিছুই পাইনি

আমার কোডটি হ'ল:

var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
// Can following code be reduced to something like _.XX(arr, {id:1}, {id:1, name: "New Name"});
_.each(arr, function(a, idx){
  if(a.id === 1){
    arr[idx] = {id:1, name: "Person New Name"};
    return false;
  }
});

_.each(arr, function(a){
  document.write(a.name);
});

আপডেট: আমি যে বস্তুর সাথে প্রতিস্থাপনের চেষ্টা করছি তার অনেকগুলি বৈশিষ্ট্য রয়েছে

{আইডি: 1, প্রোপ 1: ..., প্রোপ 2: ..., এবং আরও}

সমাধান:

ডিএফএসকিউর জন্য ধন্যবাদ তবে লড্যাশের মধ্যে আমি একটি সঠিক সমাধান খুঁজে পেয়েছি যা ভাল কাজ করে বলে মনে হচ্ছে এবং বেশ ঝরঝরে এবং আমি অনেক জায়গায় এই প্রয়োজনীয়তার কারণে এটি একটি মিশ্রণে রেখেছি। JSBin

var update = function(arr, key, newval) {
  var match = _.find(arr, key);
  if(match)
    _.merge(match, newval);
  else
    arr.push(newval);    
};

_.mixin({ '$update': update });

var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];

_.$update(arr, {id:1}, {id:1, name: "New Val"});


document.write(JSON.stringify(arr));

দ্রুত সমাধান যেমন @ ডিএফএসকিউ দ্বারা চিহ্নিত করা হয়েছে, নিম্নলিখিতটি দ্রুততর উপায়

var upsert = function (arr, key, newval) {
    var match = _.find(arr, key);
    if(match){
        var index = _.indexOf(arr, _.find(arr, key));
        arr.splice(index, 1, newval);
    } else {
        arr.push(newval);
    }
};

7
আমি মনে করি আপনি আপনার "দ্রুত সমাধান" এর লাইন 4-তে ইন্ডেক্সফ থেকে দ্বিতীয় প্যারাম হিসাবে ম্যাচটি ব্যবহার করতে পারেন, সেই মানটি সেখানে পুনরায় গণনার দরকার নেই, যা জিনিসগুলিকে কিছুটা দ্রুত করা উচিত।
দ্যাভেট্রন

2
আরও দ্রুত: _.findIndexম্যাচের জন্য ব্যবহার করুন ।
জুলিয়ান কে

1
শুধু প্রসারিত করতে হবে তা @JulianK এবং @davertron বললেন, ব্যবহার _.findIndexপরিবর্তে _.findআপনি উভয় দ্বিতীয় ড্রপ দেওয়া হবে _.findএবং _.indexOf। আপনার প্রয়োজনীয় সমস্ত 1 হয়ে গেলে আপনি 3 বার অ্যারে দিয়ে পুনরাবৃত্তি করছেন
জাস্টিন মরগান

উত্তর:


191

আপনার ক্ষেত্রে আপনাকে যা করতে হবে তা হ'ল অ্যারেতে অবজেক্ট এবং Array.prototype.splice()পদ্ধতি ব্যবহার করা , এখানে আরও বিশদ পড়ুন :

var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];

// Find item index using _.findIndex (thanks @AJ Richardson for comment)
var index = _.findIndex(arr, {id: 1});

// Replace item at index using native splice
arr.splice(index, 1, {id: 100, name: 'New object.'});

// "console.log" result
document.write(JSON.stringify( arr ));
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>


1
আচ্ছা আপনার সমাধানটি পারফরম্যান্সের ক্ষেত্রে আরও বেশি ব্যয় করতে চলেছে, যেহেতু indexOfখুব দ্রুত হতে চলেছে (এটি নেটিভ ব্রাউজারগুলি অ্যারে.প্রোটোটাইপ.ইন্ডেক্সফ ব্যবহার করবে)। তবে যাইহোক, খুশি যে আপনি একটি সমাধান খুঁজে পেয়েছেন যা আপনার পক্ষে কার্যকর।
dfsq

14
কেন ব্যবহার _.findIndexকরবেন না ? তাহলে আপনার ব্যবহারের দরকার নেই _.indexOf
এজে রিচার্ডসন

35

সহজ সমাধানটি ES6 এর .mapবা লোডাশ ব্যবহার করতে হবে বলে মনে হচ্ছে _.map:

var arr = [{id: 1, name: "Person 1"}, {id: 2, name: "Person 2"}];

// lodash
var newArr = _.map(arr, function(a) {
  return a.id === 1 ? {id: 1, name: "Person New Name"} : a;
});

// ES6
var newArr = arr.map(function(a) {
  return a.id === 1 ? {id: 1, name: "Person New Name"} : a;
});

এটির মূল অ্যারেটি পরিবর্তন করা এড়ানোয়ের দুর্দান্ত প্রভাব রয়েছে।


8
তবে আপনি প্রতিবার একটি নতুন অ্যারে তৈরি করছেন ... লক্ষ করার মতো বিষয়।
kboom

3
নতুন অ্যারে তৈরি না করার একমাত্র বিকল্প হ'ল বিদ্যমানটিকে পরিবর্তন করা। এছাড়াও, নতুন অ্যারে তৈরি করা সম্ভবত পারফরম্যান্সের ক্ষেত্রে কোনও প্রভাব ফেলবে না। আমার কাছ থেকে উড়িয়ে দেওয়া।
নোবিতা

24

[ES6] এই কোডটি আমার পক্ষে কাজ করে।

let result = array.map(item => item.id === updatedItem.id ? updatedItem : item)

১. আপনি অ্যারেটির একটি নতুন উদাহরণ তৈরি করছেন, সুতরাং এটি কোনও আইটেম "প্রতিস্থাপন" সত্য নয় true ২. updatedItemঅ্যারে যদি কোনও আইটেম অন্তর্ভুক্ত না থাকে তবে আপনি আপনার হারিয়ে ফেলবেন id
অশুভ

এটি 'আপডেট' নয় 'উপস্থাপনের' জন্য সমাধান (প্রশ্নটি ছিল "ম্যাচড আইটেমটি প্রতিস্থাপনের জন্য লোডাসে কোনও ফাংশন রয়েছে") এবং হ্যাঁ, এটি অ্যারের একটি অনুলিপি তৈরি করে, তাই আপনার যদি কাজ করার দরকার হয় তবে এটি ব্যবহার করবেন না একই অ্যারে (আমি করিনি)
শেবিক

21
function findAndReplace(arr, find, replace) {
  let i;
  for(i=0; i < arr.length && arr[i].id != find.id; i++) {}
  i < arr.length ? arr[i] = replace : arr.push(replace);
}

এখন আসুন সমস্ত পদ্ধতির জন্য পারফরম্যান্স পরীক্ষা করি:


6
জনগণের সাথে নেতিবাচক হওয়া ("এটি কি কোনও প্রকারের রসিকতা") তাদের পড়াশুনা থেকে বিরত রাখার কারণে ডাউনভোটেড। ভাবুন আমি যদি "স্মার্ট ব্যক্তি হয়ে এই কাজটি শেষ করেছি তবে আমি আশা করব যে আপনি আপনার আবেগ সম্পর্কে অলস না হন এবং সে সম্পর্কে ভাবেন না"।
আদিত্য এমপি

5
আমি কাউকে আঘাত করতে চাইনি, তবে আমি অবাক হয়েছি যে মূল বিষয়টির স্রষ্টার পদ্ধতির চেয়ে খারাপতম সমাধান কীভাবে এত বেশি ভোট পেল। যে লোকেরা তার পক্ষে তাদের ভোট দিয়েছিল তা কী নিয়ম করে? আমি হতাশ হয়েছি যে লোকেরা অন্ধভাবে সর্বাধিক ভোট দেওয়া উত্তরে বিশ্বাস করে এবং সমালোচনামূলক চিন্তাভাবনা রাখে না।
8:21

1
@ ইভিলিভ বৈধ পয়েন্ট, তবে আমি দেখতে পাচ্ছি না যে কীভাবে আপনার আগে আসা উত্তরগুলি / ভোট সরবরাহ করা প্রত্যেকে বোকামি হয়ে যায়। এই উত্তরের বাস্তব অংশগুলি দুর্দান্ত, বাকীগুলিতে সবেমাত্র রয়েছে উচ্চতর জটিলতার বায়ু। এটি কাউকে সাহায্য করে না। অতিরিক্ত সংবেদনশীল প্রতিক্রিয়া ছাড়াই আপনি সহজেই আপনার পয়েন্টগুলি তৈরি করতে পারেন।
Thor84no

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

10

আপনি ফাইন্ড ইন্ডেক্সও ব্যবহার করতে পারেন এবং একই ফলাফলটি অর্জন করতে বেছে নিতে পারেন:

  var arr  = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
  var data = {id: 2, name: 'Person 2 (updated)'};
  var index = _.findIndex(arr, _.pick(data, 'id'));
  if( index !== -1) {
    arr.splice(index, 1, data);
  } else {
    arr.push(data);
  }

6

সময় পার হওয়ার সাথে সাথে আপনাকে আরও কার্যকরী পদ্ধতির আলিঙ্গন করা উচিত যাতে আপনাকে ডেটা মিউটেশনগুলি এড়ানো এবং ছোট, একক দায়িত্ব ফাংশন লিখতে হবে। এর নাম ECMAScript 6 মান সঙ্গে, আপনার দেওয়া সঙ্গে জাভাস্ক্রিপ্ট মধ্যে কার্যকরী প্রোগ্রামিং দৃষ্টান্ত উপভোগ করতে পারেন map, filterএবং reduceপদ্ধতি। আপনার আর কোনও লড্যাশ, আন্ডারস্কোর বা সর্বাধিক প্রাথমিক কাজগুলি করার দরকার নেই।

নীচে নীচে আমি বিভিন্ন ভাষার বৈশিষ্ট্য ব্যবহার করে কীভাবে এই সমস্যা সমাধান করা যেতে পারে তা বোঝাতে এই সমস্যার কিছু প্রস্তাবিত সমাধান অন্তর্ভুক্ত করেছি:

ES6 মানচিত্র ব্যবহার:

const replace = predicate => replacement => element =>
  predicate(element) ? replacement : element
 
const arr = [ { id: 1, name: "Person 1" }, { id:2, name:"Person 2" } ];
const predicate = element => element.id === 1
const replacement = { id: 100, name: 'New object.' }

const result = arr.map(replace (predicate) (replacement))
console.log(result)


পুনরাবৃত্ত সংস্করণ - ম্যাপিংয়ের সমতুল্য:

প্রয়োজন ডেসট্রাকচারিং এবং অ্যারে বিস্তার

const replace = predicate => replacement =>
{
  const traverse = ([head, ...tail]) =>
    head
    ? [predicate(head) ? replacement : head, ...tail]
    : []
  return traverse
}
 
const arr = [ { id: 1, name: "Person 1" }, { id:2, name:"Person 2" } ];
const predicate = element => element.id === 1
const replacement = { id: 100, name: 'New object.' }

const result = replace (predicate) (replacement) (arr)
console.log(result)


যখন চূড়ান্ত অ্যারের ক্রমটি গুরুত্বপূর্ণ না হয় আপনি objectএকটি হ্যাশম্যাপ ডেটা স্ট্রাকচার হিসাবে ব্যবহার করতে পারেন । খুব সহজেই যদি আপনার কাছে ইতিমধ্যে সংগ্রহ হিসাবে কীড রয়েছে object- অন্যথায় আপনাকে প্রথমে আপনার উপস্থাপনাটি পরিবর্তন করতে হবে।

প্রয়োজন বস্তুর বাকি বিস্তার , কম্পিউটেড অবস্থায় বৈশিষ্টগুলির নাম এবং Object.entries

const replace = key => ({id, ...values}) => hashMap =>
({
  ...hashMap,       //original HashMap
  [key]: undefined, //delete the replaced value
  [id]: values      //assign replacement
})

// HashMap <-> array conversion
const toHashMapById = array =>
  array.reduce(
    (acc, { id, ...values }) => 
    ({ ...acc, [id]: values })
  , {})
  
const toArrayById = hashMap =>
  Object.entries(hashMap)
  .filter( // filter out undefined values
    ([_, value]) => value 
  ) 
  .map(
    ([id, values]) => ({ id, ...values })
  )

const arr = [ { id: 1, name: "Person 1" }, { id:2, name:"Person 2" } ];
const replaceKey = 1
const replacement = { id: 100, name: 'New object.' }

// Create a HashMap from the array, treating id properties as keys
const hashMap = toHashMapById(arr)
console.log(hashMap)

// Result of replacement - notice an undefined value for replaced key
const resultHashMap = replace (replaceKey) (replacement) (hashMap)
console.log(resultHashMap)

// Final result of conversion from the HashMap to an array
const result = toArrayById (resultHashMap)
console.log(result)


5

যদি আপনি কেবল একটি সম্পত্তি, লোড্যাশ প্রতিস্থাপনের চেষ্টা করছেন _.findএবং _.setপর্যাপ্ত পরিমাণে হওয়া উচিত:

var arr = [{id: 1, name: "Person 1"}, {id: 2, name: "Person 2"}];

_.set(_.find(arr, {id: 1}), 'name', 'New Person');

1

যদি নতুন অবজেক্টের সন্নিবেশ বিন্দুটি পূর্ববর্তী বস্তুর সূচকের সাথে মিলে যাওয়ার প্রয়োজন না হয় তবে লোডাশের সাথে এটি করার সহজতম উপায়টি হ'ল অ্যারেটিতে _.rejectনতুন মানগুলি চাপানো :

var arr = [
  { id: 1, name: "Person 1" }, 
  { id: 2, name: "Person 2" }
];

arr = _.reject(arr, { id: 1 });
arr.push({ id: 1, name: "New Val" });

// result will be: [{ id: 2, name: "Person 2" }, { id: 1, name: "New Val" }]

যদি আপনার একাধিক মান থাকে যা আপনি একটি পাসে প্রতিস্থাপন করতে চান তবে আপনি নিম্নলিখিতটি করতে পারেন (নন-ইএস 6 বিন্যাসে লিখিত):

var arr = [
  { id: 1, name: "Person 1" }, 
  { id: 2, name: "Person 2" }, 
  { id: 3, name: "Person 3" }
];

idsToReplace = [2, 3];
arr = _.reject(arr, function(o) { return idsToReplace.indexOf(o.id) > -1; });
arr.push({ id: 3, name: "New Person 3" });
arr.push({ id: 2, name: "New Person 2" });


// result will be: [{ id: 1, name: "Person 1" }, { id: 3, name: "New Person 3" }, { id: 2, name: "New Person 2" }]

এই পদ্ধতিটি অ্যারে বাছাইয়ের পরিবর্তন করে
সসপড্রা

1

লড্যাশ ইউনিয়ন ফাংশন ব্যবহার করে, আপনি কোনও অবজেক্টের একটি সহজ উপস্থাপনা সম্পন্ন করতে পারেন। ডকুমেন্টেশনে উল্লেখ করা হয়েছে যে কোনও মিল থাকলে এটি প্রথম অ্যারে ব্যবহার করবে। আপনার আপডেট হওয়া অবজেক্টটি [] (অ্যারে) এ মোড়ুন এবং ইউনিয়ন ফাংশনের প্রথম অ্যারে হিসাবে রাখুন। কেবল আপনার মিলে যাওয়া যুক্তি সুনির্দিষ্টভাবে উল্লেখ করুন এবং যদি এটি পাওয়া যায় তবে এটি এটি প্রতিস্থাপন করবে এবং না পাওয়া গেলে এটি যুক্ত করবে

উদাহরণ:

let contacts = [
     {type: 'email', desc: 'work', primary: true, value: 'email prim'}, 
     {type: 'phone', desc: 'cell', primary: true, value:'phone prim'},
     {type: 'phone', desc: 'cell', primary: false,value:'phone secondary'},
     {type: 'email', desc: 'cell', primary: false,value:'email secondary'}
]

// Update contacts because found a match
_.unionWith([{type: 'email', desc: 'work', primary: true, value: 'email updated'}], contacts, (l, r) => l.type == r.type && l.primary == r.primary)

// Add to contacts - no match found
_.unionWith([{type: 'fax', desc: 'work', primary: true, value: 'fax added'}], contacts, (l, r) => l.type == r.type && l.primary == r.primary)

1

খারাপ রূপটিও নয়)

var arr = [{id: 1, name: "Person 1"}, {id: 2, name: "Person 2"}];

var id = 1; //id to find

arr[_.find(arr, {id: id})].name = 'New Person';


0

আপনি যদি সংগ্রহের স্থিতিশীলভাবে পরিবর্তন করার কোনও উপায় খুঁজছেন (যেমন আমি যখন আপনার প্রশ্নটি পেয়েছিলাম তখন), আপনি সম্ভবত অপ্রয়োজনীয়তা-সহায়ককে দেখে নিন , মূল প্রতিক্রিয়া ব্যবহারের জন্য প্রতিষ্ঠিত একটি লাইব্রেরি। আপনার ক্ষেত্রে, আপনি নিম্নলিখিতটির মাধ্যমে যা উল্লেখ করেছেন তা সম্পাদন করবেন:

var update = require('immutability-helper')
var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}]
var newArray = update(arr, { 0: { name: { $set: 'New Name' } } })
//=> [{id: 1, name: "New Name"}, {id:2, name:"Person 2"}]

0

আপনি লোডাশ ব্যবহার না করে এটি করতে পারেন।

let arr = [{id: 1, name: "Person 1"}, {id: 2, name: "Person 2"}];
let newObj = {id: 1, name: "new Person"}

/*Add new prototype function on Array class*/
Array.prototype._replaceObj = function(newObj, key) {
  return this.map(obj => (obj[key] === newObj[key] ? newObj : obj));
};

/*return [{id: 1, name: "new Person"}, {id: 2, name: "Person 2"}]*/
arr._replaceObj(newObj, "id") 

0

অপরিবর্তনীয় , এর জন্য উপযুক্ত ReactJS:

ধরে:

cosnt arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];

আপডেট হওয়া আইটেমটি দ্বিতীয় এবং নামটি এতে পরিবর্তন করা হয়েছে Special Person:

const updatedItem = {id:2, name:"Special Person"};

ইঙ্গিত : লোটাসের দরকারী সরঞ্জাম রয়েছে তবে এখন আমাদের কাছে কিছু রয়েছে ইকামাস্ক্রিপ্ট ++ তে, সুতরাং আমি কেবলমাত্রmapফাংশনটিব্যবহারকরি যা উভয়lodashএবংecmascript6+:

const newArr = arr.map(item => item.id === 2 ? updatedItem : item);

0

পাশাপাশি এটি এসেছিল এবং এটি সহজভাবে এটি করে।

const persons = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
const updatedPerson = {id: 1, name: "new Person Name"}
const updatedPersons = persons.map(person => (
  person.id === updated.id
    ? updatedPerson
    : person
))

চাইলে আমরা এটিকে সাধারণীকরণ করতে পারি can

const replaceWhere = (list, predicate, replacement) => {
  return list.map(item => predicate(item) ? replacement : item)
}

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