Skip to content

toggle

在数组中切换元素的存在状态。如果元素存在则移除,如果不存在则添加。

基础用法

typescript
import { toggle } from 'radash'

const fruits = ['apple', 'banana', 'cherry']

const updated = toggle(fruits, 'banana')
// ['apple', 'cherry'] (banana被移除)

const updated2 = toggle(fruits, 'orange')
// ['apple', 'banana', 'cherry', 'orange'] (orange被添加)

语法

typescript
function toggle<T>(
  array: readonly T[],
  item: T
): T[]

参数

  • array (readonly T[]): 要操作的数组
  • item (T): 要切换的元素

返回值

返回一个新数组,包含切换后的元素。

示例

基本切换

typescript
import { toggle } from 'radash'

const tags = ['javascript', 'react', 'typescript']

// 移除存在的元素
const withoutReact = toggle(tags, 'react')
// ['javascript', 'typescript']

// 添加不存在的元素
const withVue = toggle(tags, 'vue')
// ['javascript', 'react', 'typescript', 'vue']

切换数字

typescript
import { toggle } from 'radash'

const numbers = [1, 2, 3, 4, 5]

const withoutThree = toggle(numbers, 3)
// [1, 2, 4, 5]

const withSix = toggle(numbers, 6)
// [1, 2, 3, 4, 5, 6]

切换对象

typescript
import { toggle } from 'radash'

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
]

const userToToggle = { id: 2, name: 'Bob' }

const updated = toggle(users, userToToggle)
// [{ id: 1, name: 'Alice' }] (Bob被移除)

const newUser = { id: 3, name: 'Charlie' }
const withNewUser = toggle(users, newUser)
// [
//   { id: 1, name: 'Alice' },
//   { id: 2, name: 'Bob' },
//   { id: 3, name: 'Charlie' }
// ]

切换布尔值

typescript
import { toggle } from 'radash'

const flags = [true, false, true]

const withoutTrue = toggle(flags, true)
// [false, true] (第一个true被移除)

const withFalse = toggle(flags, false)
// [true, false, true, false] (false被添加)

在状态管理中使用

typescript
import { toggle } from 'radash'

interface Todo {
  id: number
  text: string
  completed: boolean
}

class TodoManager {
  private todos: Todo[] = []

  toggleTodo(todoId: number) {
    const todo = this.todos.find(t => t.id === todoId)
    if (todo) {
      this.todos = toggle(this.todos, todo)
    }
  }

  addTodo(text: string) {
    const newTodo: Todo = {
      id: Date.now(),
      text,
      completed: false
    }
    this.todos = toggle(this.todos, newTodo)
  }

  getTodos() {
    return this.todos
  }
}

const manager = new TodoManager()
manager.addTodo('Learn React')
manager.addTodo('Build app')
manager.toggleTodo(manager.getTodos()[0].id) // 移除第一个todo

处理标签系统

typescript
import { toggle } from 'radash'

class TagManager {
  private selectedTags: string[] = []

  toggleTag(tag: string) {
    this.selectedTags = toggle(this.selectedTags, tag)
  }

  getSelectedTags() {
    return this.selectedTags
  }

  hasTag(tag: string) {
    return this.selectedTags.includes(tag)
  }
}

const tagManager = new TagManager()
tagManager.toggleTag('javascript')
tagManager.toggleTag('react')
tagManager.toggleTag('javascript') // 移除javascript

console.log(tagManager.getSelectedTags()) // ['react']

处理权限系统

typescript
import { toggle } from 'radash'

interface Permission {
  id: string
  name: string
  description: string
}

class PermissionManager {
  private userPermissions: Permission[] = []

  togglePermission(permission: Permission) {
    this.userPermissions = toggle(this.userPermissions, permission)
  }

  hasPermission(permissionId: string): boolean {
    return this.userPermissions.some(p => p.id === permissionId)
  }

  getPermissions() {
    return this.userPermissions
  }
}

const permissionManager = new PermissionManager()
const readPermission: Permission = { id: 'read', name: 'Read', description: 'Read access' }
const writePermission: Permission = { id: 'write', name: 'Write', description: 'Write access' }

permissionManager.togglePermission(readPermission)
permissionManager.togglePermission(writePermission)
permissionManager.togglePermission(readPermission) // 移除read权限

console.log(permissionManager.getPermissions()) // [writePermission]

处理收藏功能

typescript
import { toggle } from 'radash'

interface Bookmark {
  id: string
  url: string
  title: string
  timestamp: number
}

class BookmarkManager {
  private bookmarks: Bookmark[] = []

  toggleBookmark(bookmark: Bookmark) {
    this.bookmarks = toggle(this.bookmarks, bookmark)
  }

  isBookmarked(url: string): boolean {
    return this.bookmarks.some(b => b.url === url)
  }

  getBookmarks() {
    return this.bookmarks
  }
}

const bookmarkManager = new BookmarkManager()
const bookmark: Bookmark = {
  id: '1',
  url: 'https://example.com',
  title: 'Example',
  timestamp: Date.now()
}

bookmarkManager.toggleBookmark(bookmark) // 添加书签
bookmarkManager.toggleBookmark(bookmark) // 移除书签

处理购物车

typescript
import { toggle } from 'radash'

interface CartItem {
  id: string
  name: string
  price: number
  quantity: number
}

class ShoppingCart {
  private items: CartItem[] = []

  toggleItem(item: CartItem) {
    this.items = toggle(this.items, item)
  }

  getItems() {
    return this.items
  }

  getTotal() {
    return this.items.reduce((sum, item) => sum + (item.price * item.quantity), 0)
  }
}

const cart = new ShoppingCart()
const laptop: CartItem = { id: '1', name: 'Laptop', price: 999, quantity: 1 }
const phone: CartItem = { id: '2', name: 'Phone', price: 599, quantity: 1 }

cart.toggleItem(laptop) // 添加笔记本
cart.toggleItem(phone)  // 添加手机
cart.toggleItem(laptop) // 移除笔记本

console.log(cart.getItems()) // [phone]
console.log(cart.getTotal()) // 599

处理过滤器

typescript
import { toggle } from 'radash'

class FilterManager {
  private activeFilters: string[] = []

  toggleFilter(filter: string) {
    this.activeFilters = toggle(this.activeFilters, filter)
  }

  isFilterActive(filter: string): boolean {
    return this.activeFilters.includes(filter)
  }

  getActiveFilters() {
    return this.activeFilters
  }

  clearFilters() {
    this.activeFilters = []
  }
}

const filterManager = new FilterManager()
filterManager.toggleFilter('category:electronics')
filterManager.toggleFilter('price:under-100')
filterManager.toggleFilter('category:electronics') // 移除电子分类

console.log(filterManager.getActiveFilters()) // ['price:under-100']

处理多选列表

typescript
import { toggle } from 'radash'

class MultiSelectList {
  private selectedItems: any[] = []

  toggleItem(item: any) {
    this.selectedItems = toggle(this.selectedItems, item)
  }

  getSelectedItems() {
    return this.selectedItems
  }

  isSelected(item: any): boolean {
    return this.selectedItems.includes(item)
  }

  selectAll(items: any[]) {
    this.selectedItems = [...items]
  }

  clearSelection() {
    this.selectedItems = []
  }
}

const multiSelect = new MultiSelectList()
const options = ['Option 1', 'Option 2', 'Option 3', 'Option 4']

multiSelect.toggleItem('Option 1')
multiSelect.toggleItem('Option 2')
multiSelect.toggleItem('Option 1') // 取消选择Option 1

console.log(multiSelect.getSelectedItems()) // ['Option 2']

注意事项

  1. 保持原数组不变: toggle 不会修改原数组,而是返回新的数组
  2. 引用比较: 使用严格相等(===)来比较元素
  3. 对象比较: 对于对象,需要相同的引用才能移除
  4. 性能: 时间复杂度为 O(n),其中 n 是数组长度
  5. 重复元素: 如果有多个相同的元素,只移除第一个

与其他方法的区别

  • push() + filter(): 需要手动检查元素是否存在
  • toggle(): radash提供的简洁的切换方法
  • includes() + 条件操作: 需要更多的代码来实现相同功能

实际应用场景

  1. 标签系统: 添加/移除标签
  2. 权限管理: 授予/撤销权限
  3. 收藏功能: 添加/移除收藏
  4. 购物车: 添加/移除商品
  5. 多选列表: 选择/取消选择项目

Released under the MIT License.