Modulo를 사용하여 숫자 범위를 감싸는 방법

10577 단어 javascriptmodulo
우리는 JavaScript를 사용할 것이지만 모듈로 연산자를 사용하는 모든 언어에서 작동해야 합니다.

TLDR;



때로는 1-10과 같은 숫자 범위가 있습니다. 함수가 최소값 이하 또는 최대값 이상으로 이동하지 않고 범위 내에서 인덱스를 증가 및 감소시키길 원합니다. 모듈로 연산자가 이를 수행합니다.

사용 사례



나는 최근에 Stimulus.js에 대한 가이드를 따라가다가 이 문제를 만났습니다.

관심이 있다면 Stimulus는 Ruby on Rails 7에서 표준으로 제공되는 JavaScript 프레임워크입니다. 저는 Ruby에서 코딩하고 Rails를 사용하는 것을 좋아하기 때문에 이를 배우고 있습니다. 요소에 데이터 속성을 추가하여 Javascript로 DOM 요소를 쉽게 조작할 수 있습니다.

가이드는 두 개의 버튼이 표시되거나 숨겨진 4개의 div 목록을 전환하는 슬라이드쇼와 같은 기능을 만드는 과정을 안내했습니다.

문제는 현재 인덱스가 0일 때 이전을 클릭하면 인덱스가 -1로 감소한다는 것입니다. 마찬가지로 인덱스 3(목록의 네 번째 항목)에 있는 경우 인덱스가 5로 증가합니다. 원하는 동작은 첫 번째/마지막 요소로 래핑하는 것입니다.

증가
0 → 1 → 2 → 3 → 0 → 1

감소
2 ← 3 ← 0 ← 1 ← 2 ← 3

당신은 아이디어를 얻을!

Javascript를 사용하여 이것을 달성하는 방법!



// let's start by defining a simple class Range 

class Range {
  constructor(index) {
    this.index = index;
  }

  // here are our two methods.  We will return the index
  // so that it's easy to see what's happening
  next() {
    this.index++
    return this.index
  }

  previous() {
    this.index--
    return this.index
  }
}

따라서 여기의 목표는 Range의 새 인스턴스를 인스턴스화하고 인덱스를 증가 및 감소시키는 두 가지 방법을 사용하여 0-4를 반복하면서 0 이하 또는 4 이상으로 이동하지 않는 것입니다. 물론... 이것은 작동하지 않습니다.

// our class allows us to specify the starting range.
// we could have set the default to 0 as well.

let range = new Range(0);


이제 메서드를 호출하고 인덱스에 어떤 일이 발생하는지 살펴보겠습니다.

range.index
=> 0
range.next()
=> 1
range.next()
=> 2
range.index
=> 2
// cool! it's works

range.next()
=> 3
range.next()
=> 4
range.next()
=> 5
range.next()
=> 6
// oops! too high!
// let's bring it down.
range.previous()
=> 5
range.previous()
=> 4
range.previous()
=> 3
range.previous()
=> 2
range.previous()
=> 1
range.previous()
=> 0
range.previous()
=> -1
range.previous()
=> -2
// oops!  too low!


이제 우리가 달성하려는 것이 분명해졌으면 합니다. 이제 해결책을 찾아봅시다.

모듈로 연산자 사용



그것은 무엇입니까? TLDR; 나눗셈 후 나머지를 반환합니다.

3을 2로 나눈 값은 1이고 나머지는 1입니다. 나머지 값만 원한다면 어떻게 할까요? 우리 친구 모듈로를 사용하십시오. 퍼센트 기호일 뿐입니다.

3% 2 => 1
10% 8 => 2
5% 5 => 0
4% 2 => 0
6% 3 => 0
7% 4 => 3
156% 37 => 8

오른쪽에 더 큰 숫자가 있는 모듈로를 사용할 때마다 왼쪽에 있는 숫자가 반환됩니다.

1% 10 => 1
1% 2 => 1
5% 6 => 5
5% 10000 => 5

Modulo는 실제로 몇 가지 멋진 작업을 수행할 수 있습니다! Ruby에서 2D 우주선 게임을 코딩하면서 처음으로 실용성을 보았습니다. 모듈로 연산자는 우주선이 화면을 벗어나 다른 쪽에서 다시 들어올 수 있도록 허용했습니다. 여기에서도 비슷한 목적을 수행할 것입니다.

내 인덱스가 0이라고 가정해 보겠습니다. 여기에 1을 더하고 싶지만 숫자 4를 넘지 않도록 하고 싶습니다. 따라서 5는 범위 0,1,2,3,4의 길이입니다.

그래서 내가 하는 일은 범위 길이(5) 모듈로 범위 길이(5)를 더한 증가량(1)을 더한 자체 합계에 원래 인덱스(1)를 할당하는 것입니다.
index = (index + rangeLength + incrementAmount) % rangeLength
아직 마음이 날아 갔습니까? 🤯

사용해 보세요!

Assign the original index to the sum of itself plus the range length plus the increment modulo the range length.


보정! 증분할 때 범위 길이를 추가할 필요가 없습니다. 해도 아프지 않습니다. 따라서 index = (index + 1) % rangeLength를 수행할 수 있습니다. 감소할 때 범위 길이를 추가해야 합니다.


index = 0index = (0 + 5 + 1) % 5 => 1
6을 5로 나눈 나머지는 1입니다. 따라서 이제 인덱스는 1입니다.
index = (1 + 5 + 1) % 5 => 2index = (2 + 5 + 1) % 5 => 3index = (3 + 5 + 1) % 5 => 4index = (4 + 5 + 1) % 5 => 0
그것은 효과가 있었다! 10을 5로 나누면 나머지가 없기 때문에 인덱스는 이제 0에서 다시 시작됩니다.

이제 감소 방법을 사용해 봅시다. 범위 길이에서 범위 길이로 나눈 감소량을 뺀 나머지 자체에 인덱스를 할당하기만 하면 됩니다.
index = (index + rangeLength - decrementAmount) % rangeLengthlet index = 4index = (4 + 5 - 1) % 5 => 3index = (3 + 5 - 1) % 5 => 2index = (2 + 5 - 1) % 5 => 1index = (1 + 5 - 1) % 5 => 0index = (0 + 5 - 1) % 5 => 4
이제 이를 구현하기 위해 Range 클래스를 편집할 수 있습니다.

class Range {
  constructor(index) {
    this.index = index;
    this.length = 5;
    this.incrementAmount = 1;
    this.decrementAmount = 1;
  }

  next() {
    this.index = (this.index + this.length + this.incrementAmount) % this.length;
    return this.index
  }

  previous() {
    this.index = (this.index + this.length - this.decrementAmount) % this.length;
    return this.index
  }
}


이제 테스트해 보세요. 우리의 next()previous() 방법이 완벽하게 작동합니다!

좋은 웹페이지 즐겨찾기