Skip to content

Commit

Permalink
refactor: update array add, remove, toggle and replaceAt to be mutati…
Browse files Browse the repository at this point in the history
…ng array methods
  • Loading branch information
jorenrui committed Mar 17, 2024
1 parent 921ee7f commit 236606b
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 63 deletions.
63 changes: 27 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -455,39 +455,56 @@ Here are the custom array methods which are available for you to use:
array.last // returns 'Vanilla'
```

- `search` - returns an array of items that match the query.
- `search` - returns a new array of items that match the query.
Usage: `array.search('query')`

```js
array = ['Cherries', 'Chocolate', 'Blueberry', 'Vanilla']
array.search('c') // returns ['Cherries', 'Chocolate']
```

- `add` - adds an item to the array if it doesn't exist.
Usage: `array.add('item')`
- `subtract` - removes a list of items from the array if they exist.
Usage: `array.subtract(['item1', 'item2'])`

```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.add('Tag 5') // returns ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4', 'Tag 5']
array.subtract(['Tag 2', 'Tag 3']) // returns ['Tag 1', 'Tag 4']
```

- `subtract` - removes a list of items from the array if they exist.
Usage: `array.subtract(['item1', 'item2'])`
- `nextItem` - gets the next item based on the given item in the array.
Usage: `array.nextItem('item')`
```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.nextItem('Tag 2') // returns 'Tag 3'
```
- `previousItem` - gets the next item based on the given item in the array.
Usage: `array.previousItem('item')`

```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.subtract(['Tag 2', 'Tag 3']) // returns ['Tag 1', 'Tag 4']
array.previousItem('Tag 2') // returns 'Tag 1'
```

- `remove` - removes an item from the array if it exists.
- `add` - adds an item to the original array if it doesn't exist.
- This mutates the original array.
Usage: `array.add('item')`

```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.add('Tag 5') // returns ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4', 'Tag 5']
```

- `remove` - removes an item from the original array if it exists.
- This mutates the original array.
Usage: `array.remove('item')`

```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.remove('Tag 2') // returns ['Tag 1', 'Tag 3', 'Tag 4']
```

- `toggle` - removes / adds the item in the array
- `toggle` - removes / adds the item in the original array
- This mutates the original array.
Usage: `array.toggle('item')`

```js
Expand All @@ -500,40 +517,14 @@ Here are the custom array methods which are available for you to use:
```

- `replaceAt` - replaces the item at the given index with the new item.
- This mutates the original array.
Usage: `array.replaceAt(index, 'newItem')`

```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.replaceAt(1, 'Tag 5') // returns ['Tag 1', 'Tag 5', 'Tag 3', 'Tag 4']
```

- `nextItem` - gets the next item based on the given item in the array.
Usage: `array.nextItem('item')`
```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.nextItem('Tag 2') // returns 'Tag 3'
```
- `previousItem` - gets the next item based on the given item in the array.
Usage: `array.previousItem('item')`

```js
array = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
array.previousItem('Tag 2') // returns 'Tag 1'
```

#### Triggering Array Updates

To trigger a re-render you need to update the variable:

```js
// Will not trigger a re-render
filteredTags.remove('Chocolates')

// Will trigger a re-render due to re-assignment of the
// filteredTags variable.
filteredTags = filteredTags.remove('Chocolates')
```

## Contributors

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
Expand Down
22 changes: 11 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ <h3 class="font-bold font-mono">AirBnB Search Bar:</h3>
type="button"
class="h-36 w-28 flex flex-col items-center justify-center gap-1 text-center text-gray-900 rounded-2xl"
:class="selectedMonths.includes(month) ? 'ring-2 ring-gray-900' : 'ring-1 ring-gray-200'"
:click="selectedMonths = selectedMonths.toggle(month);"
:click="selectedMonths.toggle(month);"
>
<span
:class="selectedMonths.includes(month) ? 'text-gray-900' : 'text-gray-600'"
Expand Down Expand Up @@ -1339,8 +1339,8 @@ <h3 class="font-bold font-mono">Multi Select:</h3>
:change="searchQuery = this.value;
filteredTags = allTags.subtract(selectedTags).search(searchQuery);
selectedTag = filteredTags.first"
:keyup.enter="selectedTags = selectedTags.add(selectedTag);
filteredTags = filteredTags.remove(selectedTag);
:keyup.enter="selectedTags.add(selectedTag);
filteredTags.remove(selectedTag);
selectedTag = filteredTags.first"
:keyup.up="selectedTag = filteredTags.previousItem(selectedTag)"
:keyup.down="selectedTag = filteredTags.nextItem(selectedTag)"
Expand All @@ -1364,8 +1364,8 @@ <h3 class="font-bold font-mono">Multi Select:</h3>
>
<li
role="option"
:click="selectedTags = selectedTags.add(tag);
filteredTags = filteredTags.remove(selectedTag);
:click="selectedTags.add(tag);
filteredTags.remove(selectedTag);
selectedTag = filteredTags.first"
:mouseover="el.isHovering = true"
:mouseout="el.isHovering = false"
Expand All @@ -1392,7 +1392,7 @@ <h3 class="font-bold font-mono">Multi Select:</h3>
></span>
<span
class="px-2 py-1 text-xs text-blue-800 font-semibold ml-2 cursor-pointer rounded-full hover:bg-red-200 hover:text-red-600"
:click="selectedTags = selectedTags.remove(tag);
:click="selectedTags.remove(tag);
filteredTags = allTags.subtract(selectedTags).search(searchQuery);
selectedTag = filteredTags.first"
>
Expand Down Expand Up @@ -1420,8 +1420,8 @@ <h3 class="font-bold font-mono">Multi Select:</h3>
:change=&quot;searchQuery = this.value;
filteredTags = allTags.subtract(selectedTags).search(searchQuery);
selectedTag = filteredTags.first&quot;
:keyup.enter=&quot;selectedTags = selectedTags.add(selectedTag);
filteredTags = filteredTags.remove(selectedTag);
:keyup.enter=&quot;selectedTags.add(selectedTag);
filteredTags.remove(selectedTag);
selectedTag = filteredTags.first&quot;
:keyup.up=&quot;selectedTag = filteredTags.previousItem(selectedTag)&quot;
:keyup.down=&quot;selectedTag = filteredTags.nextItem(selectedTag)&quot;
Expand All @@ -1431,8 +1431,8 @@ <h3 class="font-bold font-mono">Multi Select:</h3>
&lt;p class=&quot;p-3 font-mono font-semibold mb-2 pb-1 border-b-2 border-gray-500 border-dashed&quot;&gt;Search Result:&lt;/p&gt;
&lt;div :each=&quot;tag in filteredTags&quot;&gt;
&lt;div
:click=&quot;selectedTags = selectedTags.add(tag);
filteredTags = filteredTags.remove(selectedTag);
:click=&quot;selectedTags.add(tag);
filteredTags.remove(selectedTag);
selectedTag = filteredTags.first&quot;
:mouseover=&quot;selectedTag = tag&quot;
:class=&quot;selectedTag == tag ? 'bg-blue-100 text-blue-700' : 'text-gray-700'&quot;
Expand All @@ -1449,7 +1449,7 @@ <h3 class="font-bold font-mono">Multi Select:</h3>
&lt;span :text=&quot;tag&quot; class=&quot;font-semibold font-mono text-xs&quot;&gt;&lt;/span&gt;
&lt;span
class=&quot;px-2 py-1 text-xs text-blue-800 font-semibold ml-2 cursor-pointer rounded-full hover:bg-red-200 hover:text-red-600&quot;
:click=&quot;selectedTags = selectedTags.remove(tag);
:click=&quot;selectedTags.remove(tag);
filteredTags = allTags.subtract(selectedTags).search(searchQuery);
selectedTag = filteredTags.first&quot;
&gt;
Expand Down
33 changes: 17 additions & 16 deletions lib/helpers/array.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export class MiniArray extends Array {
static mutateMethods = ['fill', 'pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse', 'copyWithin', 'toggle', 'add', 'remove', 'replaceAt']

constructor(...args) {
super(...args)
}
Expand All @@ -25,47 +27,46 @@ export class MiniArray extends Array {
let newValue

if (Array.isArray(value)) {
newValue = value
this.length = 0
this.push(...value)
} else {
let index = this.indexOf(value)

if (index === -1) {
newValue = this.concat(value)
this.push(value)
} else {
newValue = this.slice(0, index).concat(this.slice(index + 1))
this.splice(index, 1)
}
}

return new MiniArray(...newValue)
return this
}

add(value) {
let index = this.indexOf(value)
if (index !== -1) return this

const newValue = this.concat(value)

return new MiniArray(...newValue)
this.push(value)
return this
}

remove(value) {
let index = this.indexOf(value)
if (index === -1) return this

const newValue = this.slice(0, index).concat(this.slice(index + 1))

return new MiniArray(...newValue)
this.splice(index, 1)
return this
}

replaceAt(index, value) {
this.splice(index, 1, value)
return this
}

subtract(arr) {
return new MiniArray(...this.filter((item) => !arr.includes(item)))
}

replaceAt(index, value) {
const newValue = [...this]
newValue[index] = value
return new MiniArray(...newValue)
}

search(query) {
const normalizedQuery = query.toLowerCase().split(/\s+/)

Expand Down

0 comments on commit 236606b

Please sign in to comment.