[javascript] ImmutableJS로 List 내의 요소를 업데이트하는 방법은 무엇입니까?

공식 문서가 말한 내용은 다음과 같습니다.

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로 설정된 위치를 어떻게 업데이트 합니까?



답변

가장 적절한 경우는 방법 findIndexupdate방법을 모두 사용 하는 것입니다.

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

추신 : 항상지도를 사용할 수있는 것은 아닙니다. 예를 들어 이름이 고유하지 않고 같은 이름으로 모든 항목을 업데이트하고 싶습니다.


답변

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

그것이 도움이되기를 바랍니다!


답변

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

이제 세 번째 항목을 업데이트하려는 경우 일반 JS 배열은 다음과 같습니다 counts[2] = 4. 우리가 메소드를 호출하는 돌연변이, 그리고 필요를 사용할 수 없기 때문에, 대신에 우리가 사용할 수 있습니다 : counts.set(2, 4)– 수단 값을 설정하는 것이 4인덱스에서2 .

깊은 업데이트

당신이 준 예제는 중첩 된 데이터를 가지고 있습니다. 우리는 단지 사용할 수 없습니다set()초기 컬렉션에는 .

Immutable.js 컬렉션에는 이름이 “In”으로 끝나는 메서드 모음이 있으므로 중첩 된 집합을 더 깊이 변경할 수 있습니다. 가장 일반적인 업데이트 방법에는 관련 “입력”방법이 있습니다. 예를 들어 대한 setsetIn . 이러한 “In”메소드는 색인 또는 키를 첫 번째 인수로 승인하는 대신 “키 경로”를 승인합니다. 키 경로는 업데이트하려는 값에 도달하는 방법을 보여주는 인덱스 또는 키 배열입니다.

예를 들어, 색인 2의 목록에서 항목을 업데이트 한 다음 해당 항목 내의 “count”키의 값을 업데이트하려고합니다. 따라서 핵심 경로는입니다 [2, "count"]. setIn메소드 의 두 번째 매개 변수는 다음 과 같이 작동 set합니다.이 값은 우리가 거기에 넣고 싶은 새로운 값이므로 다음과 같습니다.

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

올바른 키 경로 찾기

한 단계 더 나아가서 실제로 이름이 “세” 인 항목을 세 번째 항목과 다른 항목으로 업데이트하고 싶다고 말했습니다 . 예를 들어 목록이 정렬되지 않았거나 “two”라는 항목이 이전에 제거 되었습니까? 즉, 먼저 올바른 키 경로를 실제로 알아야합니다. 이를 위해 우리는 findIndex()메소드 를 사용할 수 있습니다 ( 어쨌든 Array # findIndex 와 거의 동일하게 작동합니다) ).

목록에서 업데이트하려는 항목이있는 인덱스를 찾았 으면 업데이트 할 값의 키 경로를 제공 할 수 있습니다.

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

NB : SetvsUpdate

원래 질문에는 set 메소드가 아닌 업데이트 메소드가 언급되어 있습니다. 이 함수의 두 번째 인수 ()는 설명과 updater다르므로 설명하겠습니다 set(). 두 번째 인수 set()는 원하는 새 값 이지만 두 번째 인수 는 이전 값을 허용하고 원하는 새 값을 반환 update()하는 함수 입니다. 그런 다음 updateIn()“In”변형은 update()키 경로를 허용합니다.

예를 들어 카운트를로 설정하지 않고 기존 카운트 4증가 시키는 예제의 변형을 원한다면 기존 값에 1을 더하는 함수를 제공 할 수 있습니다.

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


답변

공식 문서는 다음과 같습니다. updateIn

updateIn중첩 구조에 대해서만 필요 합니다. 서명과 문서가 훨씬 간단한 update메소드를 찾고 있습니다.

기존 값으로 updater를 호출하는 반환 값 또는 index가 설정되지 않은 경우 notSetValue를 반환하여 색인에 업데이트 된 값이있는 새 List를 반환합니다.

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

하는 경우, AS Map::update문서는 제안이다 ” 동일합니다 :list.set(index, updater(list.get(index, notSetValue))) “.

이름이 “third”인 요소

그것은 목록이 작동하는 방식이 아닙니다. 업데이트하려는 요소의 색인을 알아야하거나 검색해야합니다.

이름이 세 번째 인 요소의 개수가 4로 설정된 목록을 어떻게 업데이트 할 수 있습니까?

이것은해야합니다 :

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


답변

사용 ) (.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;
});

그러나 이것은 전체 컬렉션을 반복합니다.