簡體   English   中英

如何使用ImmutableJS更新List中的元素?

[英]How to update element inside List with ImmutableJS?

這是官方文檔所說的

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>

普通的Web開發人員(非功能程序員)無法理解這一點!

我非常簡單(對於非功能性方法)的情況。

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 ,其中名稱為third的元素的計數設置為4

最合適的情況是使用findIndexupdate方法。

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

PS並不總是可以使用地圖。 例如,如果名稱不唯一,我想更新具有相同名稱的所有項目。

使用.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);

希望能幫助到你!

這是官方文檔說的...... updateIn

您不需要updateIn ,僅適用於嵌套結構。 您正在尋找update方法 ,它具有更簡單的簽名和文檔:

返回一個新的List,其索引處的更新值為使用現有值調用updater的返回值,如果未設置index,則返回notSetValue。

 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))) ”。

其中名稱為“third”的元素

這不是列表的工作方式。 您必須知道要更新的元素的索引,或者您必須搜索它。

如何更新列表,其中名稱為third的元素的計數設置為4?

這應該這樣做:

list = list.update(2, function(v) {
    return {id: v.id, name: v.name, count: 4};
});
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)

說明

更新Immutable.js集合始終返回這些集合的新版本,而原始集合保持不變。 因此,我們不能使用JavaScript的list[2].count = 4變異語法。 相反,我們需要調用方法,就像我們可能使用Java集合類一樣。

讓我們從一個更簡單的例子開始:只是列表中的計數。

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

現在,如果我們想要更新第3項,那么普通的JS數組可能看起來像: counts[2] = 4 由於我們不能使用變異,並且需要調用方法,而是我們可以使用: counts.set(2, 4) - 這意味着在索引2處設置值4

深度更新

您給出的示例包含嵌套數據。 我們不能只在初始集合上使用set()

Immutable.js集合有一系列方法,名稱以“In”結尾,允許您在嵌套集中進行更深層次的更改。 最常見的更新方法具有相關的“In”方法。 例如,對於setsetIn 這些“In”方法不接受索引或鍵作為第一個參數,而是接受“關鍵路徑”。 關鍵路徑是索引或鍵的數組,用於說明如何獲取要更新的值。

在您的示例中,您希望更新索引2中列表中的項目,然后更新該項目中鍵“count”的值。 所以關鍵路徑是[2, "count"] setIn方法的第二個參數就像set一樣工作,它是我們想要放在那里的新值,所以:

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

找到正確的關鍵路徑

更進一步,你實際上說你想要更新名稱為“3”的項目,這與第3項不同。 例如,您的列表可能沒有排序,或者可能之前刪除了名為“two”的項目? 這意味着首先我們需要確保我們確實知道正確的關鍵路徑! 為此我們可以使用findIndex()方法(順便說一句,它的工作方式幾乎與Array#findIndex一樣 )。

一旦我們在列表中找到了包含我們想要更新的項目的索引,我們就可以提供我們希望更新的值的關鍵路徑:

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

注意: SetUpdate

原始問題提到了更新方法而不是set方法。 我將解釋該函數中的第二個參數(稱為updater ),因為它與set()不同。 而第二個參數set()是我們希望新的價值,第二個參數來update()是接受於前值和返回,我們希望新的值的函數 然后, updateIn()update()的“In”變體,它接受一個鍵路徑。

比方說,我們想要一個不僅將計數設置為4示例變體,而是增加現有計數,我們可以提供一個函數,將現有值加1:

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

使用.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> 

我非常喜歡thomastuts網站上的這種方法:

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);

你可以使用map

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

但這將遍及整個集合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM