首页 > 编程语言 >lodash已死?radash最全使用介绍(附源码说明)—— Array方法篇(3)

lodash已死?radash最全使用介绍(附源码说明)—— Array方法篇(3)

时间:2024-04-12 11:26:00浏览次数:27  
标签:const 函数 name 元素 list 已死 源码 数组 lodash

前言

  • 我们已经介绍了radash的相关信息和部分Array相关方法,详情可前往主页查看;
  • 本篇我们继续介绍radash中Array的相关方法;
  • 下期我们将介绍解析radash中剩余的 Array相关方法,并整理出Array方法使用目录,包括文章说明脑图说明

Radash的Array相关方法详解

iterate:把一个函数迭代执行指定次数

  1. 使用说明
    • 参数:迭代次数、每次迭代调用的函数、迭代初始值。
    • 返回值:返回最终一次循环迭代的值。
  2. 使用代码示例
    import { iterate } from 'radash'
    
    const value = iterate(
      4,
      (acc, idx) => {
        return acc + idx
      },
      0
    ) // => 10
    
  3. 源码解析
    // 定义一个泛型函数 `iterate`,它接收三个参数:
    // `count` 是一个数字,表示迭代的次数;
    // `func` 是一个函数,它在每次迭代中被调用,接收当前值和迭代次数作为参数,并返回一个新的值;
    // `initValue` 是迭代的初始值,它的类型为泛型 `T`。
    export const iterate = <T>(
      count: number,
      func: (currentValue: T, iteration: number) => T,
      initValue: T
    ) => {
      // 初始化一个变量 `value`,用于存储当前的迭代值,起始值设置为 `initValue`。
      let value = initValue
      // 使用一个 `for` 循环进行 `count` 次迭代。循环变量 `i` 从 1 开始,以确保迭代次数正确。
      for (let i = 1; i <= count; i++) {
        // 在每次迭代中,调用函数 `func`,传入当前的 `value` 和迭代次数 `i`,
        // 然后将 `func` 函数返回的新值赋给 `value`,以便在下一次迭代中使用。
        value = func(value, i)
      }
      // 循环结束后,返回最终的迭代值 `value`。
      return value
    }
    
    • 方法流程说明:
      1. 接收 countfuncinitValue 作为参数。
      2. 初始化变量 valueinitValue
      3. 进行 count 次迭代,每次迭代中调用 func 函数,传入当前的 value 和迭代次数 i
      4. func 函数返回一个新值,这个新值成为下一次迭代的 value
      5. 迭代完成后,返回最后一次 func 函数调用的结果。

last:输出数组的最后一项,如果数组为空则输出传入的默认值

  1. 使用说明

    • 参数:目标数组,或者空数组和默认值。
    • 返回值:数组最后一项,如果数组为空则输出传入的默认值。
  2. 使用代码示例

    import { last } from 'radash'
    
    const fish = ['marlin', 'bass', 'trout']
    
    const lastFish = last(fish) // => 'trout'
    const lastItem = last([], 'bass') // => 'bass'
    
  3. 源码解析

    // 定义一个泛型函数 `last`,它接收一个具有只读属性的泛型数组 `array`,
    // 和一个可选的默认值 `defaultValue`,其类型可以是泛型 `T` 或 `null` 或 `undefined`,默认值为 `undefined`。
    export const last = <T>(
      array: readonly T[],
      defaultValue: T | null | undefined = undefined
    ) => {
      // 如果数组存在且长度大于0,返回数组的最后一个元素。
      // 否则,返回提供的默认值 `defaultValue`。
      return array?.length > 0 ? array[array.length - 1] : defaultValue
    }
    
    • 方法流程说明:
      1. 检查传入的数组 array 是否存在且长度大于0。
      2. 如果数组存在且不为空(长度大于0),则返回数组的最后一个元素 array[array.length - 1]
      3. 如果数组不存在或为空,返回 defaultValue
      4. 这个函数对于需要安全地访问数组最后一个元素而不抛出错误的情况很有用,特别是在不确定数组是否为空的情况下。通过提供一个默认值,你可以避免在数组为空时访问未定义的索引。如果没有提供默认值,函数将默认返回 undefined

list:创建包含特定项的数组

  1. 使用说明
    • 参数:start、end、值,步长。
    • 返回值:从start开始遍历到end,输出一个数组,包含特定项(值)的数组。
  2. 使用代码示例
    import { list } from 'radash'
    
    list(3)                  // [0, 1, 2, 3]
    list(0, 3)               // [0, 1, 2, 3]
    list(0, 3, 'y')          // [y, y, y, y]
    list(0, 3, () => 'y')    // [y, y, y, y]
    list(0, 3, i => i)       // [0, 1, 2, 3]
    list(0, 3, i => `y${i}`) // [y0, y1, y2, y3]
    list(0, 3, obj)          // [obj, obj, obj, obj]
    list(0, 6, i => i, 2)    // [0, 2, 4, 6]
    
  3. 源码解析
    // 定义一个泛型函数 `list`,它接受一个默认类型参数 `T`,默认为 `number`。
    // 函数接受四个参数:起始值或长度 `startOrLength`,可选的结束值 `end`,
    // 可选的值或映射函数 `valueOrMapper` 用于生成数组中的值,以及可选的步长 `step`。
    export const list = <T = number>(
      startOrLength: number,
      end?: number,
      valueOrMapper?: T | ((i: number) => T),
      step?: number
    ): T[] => {
      // 使用 `Array.from` 方法来创建一个数组,它接受 `range` 生成器函数作为参数。
      // `range` 函数根据提供的参数生成一个序列的值。
      return Array.from(range(startOrLength, end, valueOrMapper, step))
    }
    
    • 方法流程说明:
      1. 调用 range 函数,传入 startOrLength(起始值或长度)、end(结束值)、valueOrMapper(值或映射函数)、step(步长)四个参数。这些参数都是可选的,除了 startOrLength 必须提供。
      2. range 函数是一个生成器,根据提供的参数生成一个数字序列。如果指定了 end,那么 startOrLength 作为起始值,end 作为结束值。如果没有指定 endstartOrLength 作为序列的长度。valueOrMapper 可以是一个值,此时序列中的每个元素都是这个值;也可以是一个函数,此时序列中的每个元素都是这个函数的返回值。step 指定了序列中每个元素之间的间隔。
      3. Array.from 方法用于从 range 生成器创建一个数组。生成器的每次迭代返回的值都会成为数组中的一个元素。
      4. 最终,list 函数返回这个数组。

max:获取对象数组中指定标识符最大的项

  1. 使用说明
    • 参数:目标对象数组、指定标识符的回调函数。
    • 返回值:符合条件的对象。
  2. 使用代码示例
    import { max } from 'radash'
    
    const fish = [
      {
        name: 'Marlin',
        weight: 105,
        source: 'ocean'
      },
      {
        name: 'Bass',
        weight: 8,
        source: 'lake'
      },
      {
        name: 'Trout',
        weight: 13,
        source: 'lake'
      }
    ]
    
    max(fish, f => f.weight) // => {name: "Marlin", weight: 105, source: "ocean"}
    
  3. 源码解析
    // 定义一个泛型函数 `max`,它接受一个具有只读属性的泛型数组 `array`,
    // 以及一个可选的函数 `getter`,该函数用于从数组元素中提取一个数字用于比较大小。
    export function max<T>(
      array: readonly T[],
      getter?: (item: T) => number
    ): T | null {
      // 如果 `getter` 函数未提供,则使用默认函数,它将元素作为其自己的值。
      const get = getter ?? ((v: any) => v)
      // 调用 `boil` 函数,传入数组和一个比较函数,
      // 比较函数用 `get` 函数获取的值来决定哪个元素更大。
      return boil(array, (a, b) => (get(a) > get(b) ? a : b))
    }
    
    // 定义一个泛型函数 `boil`,它接受一个具有只读属性的泛型数组 `array`,
    // 以及一个比较函数 `compareFunc`,该函数用于比较两个元素并返回其中一个。
    export const boil = <T>(
      array: readonly T[],
      compareFunc: (a: T, b: T) => T
    ) => {
      // 如果传入的数组不存在,或者其长度为0,则返回 null。
      if (!array || (array.length ?? 0) === 0) return null
      // 使用数组的 `reduce` 方法应用 `compareFunc`,将数组归约为单一的值。
      return array.reduce(compareFunc)
    }
    
    • 方法流程说明:
      1. 接收一个数组 array 和一个可选的 getter 函数。如果 getter 函数提供,它将用于从每个元素中提取用于比较的数字值。
      2. 如果没有提供 getter 函数,使用一个默认的函数,这个函数简单地返回元素本身作为比较值。
      3. 调用 boil 函数,传入数组和一个比较函数。这个比较函数使用 get 函数从两个元素 ab 中提取值,并返回较大值对应的元素。
      4. boil 函数通过 reduce 方法遍历数组,应用比较函数,并最终返回单一的元素,即数组中的最大元素。如果数组为空或未定义,boil 函数返回 null
      5. max 函数最终返回 boil 函数的结果,即数组中的最大元素,如果数组为空,则返回 null

merge:合并数组中符合条件的项,并且会覆盖第一个数组

  1. 使用说明

    • 参数:数组1、数组2、条件函数。
    • 返回值:合并覆盖后的数组。
  2. 使用代码示例

    import { merge } from 'radash'
    
    const gods = [
      {
        name: 'Zeus',
        power: 92
      },
      {
        name: 'Ra',
        power: 97
      }
    ]
    
    const newGods = [
      {
        name: 'Zeus',
        power: 100
      }
    ]
    
    merge(gods, newGods, f => f.name) // => [{name: "Zeus" power: 100}, {name: "Ra", power: 97}]
    
  3. 源码解析

    export const merge = <T>(
      root: readonly T[],
      others: readonly T[],
      matcher: (item: T) => any
    ) => {
      if (!others && !root) return []
      if (!others) return root
      if (!root) return []
      if (!matcher) return root
      return root.reduce((acc, r) => {
        const matched = others.find(o => matcher(r) === matcher(o))
        if (matched) acc.push(matched)
        else acc.push(r)
        return acc
      }, [] as T[])
    }
    
    • 方法流程说明:
      1. 进行一系列的检查,如果 othersroot 两个数组都不存在或为空,或者没有提供 matcher 函数,就返回 root 或者一个空数组。
      2. 使用 root 数组的 reduce 方法构建最终的合并数组。在每次迭代中,使用 matcher 函数检查 root 数组中的当前元素是否在 others 数组中有匹配的元素。
      3. 如果在 others 数组中找到了一个匹配的元素,就把这个匹配的元素添加到累加器数组 acc 中。
      4. 如果没有找到匹配的元素,就把 root 数组中的当前元素添加到累加器 acc 中。
      5. 继续处理 root 数组的下一个元素,直到所有元素都被处理完毕。
      6. 返回累加器 acc,它现在包含了合并后的元素。

min:获取对象数组中指定标识符最小的项

  1. 使用说明
    • 参数:目标对象数组、指定标识符的条件函数。
    • 返回值:符合条件的的项
  2. 使用代码示例
    import { min } from 'radash'
    
    const fish = [
      {
        name: 'Marlin',
        weight: 105,
        source: 'ocean'
      },
      {
        name: 'Bass',
        weight: 8,
        source: 'lake'
      },
      {
        name: 'Trout',
        weight: 13,
        source: 'lake'
      }
    ]
    
    min(fish, f => f.weight) // => {name: "Bass", weight: 8, source: "lake"}
    
  3. 源码解析
    // 这是 `min` 函数的第一种声明,它要求传递一个 `getter` 函数。
    export function min<T>(
      array: readonly T[],
      getter: (item: T) => number
    ): T | null
    
    // 这是 `min` 函数的第二种声明,它允许 `getter` 函数是可选的。
    export function min<T>(
      array: readonly T[],
      getter?: (item: T) => number
    ): T | null {
      // 如果没有提供 `getter` 函数,使用默认函数,它将元素作为其自己的值。
      const get = getter ?? ((v: any) => v)
      // 调用 `boil` 函数,传入数组和一个比较函数,
      // 比较函数用 `get` 函数获取的值来决定哪个元素更小。
      return boil(array, (a, b) => (get(a) < get(b) ? a : b))
    }
    
    • 方法流程说明:
      1. 函数接收一个数组 array 和一个可选的 getter 函数。如果提供了 getter 函数,它将用于从每个元素中提取用于比较的数字值。
      2. 如果没有提供 getter 函数,则使用一个默认的函数,这个函数简单地返回元素本身作为比较值。
      3. 调用 boil 函数,传入数组和一个比较函数。这个比较函数使用 get 函数从两个元素 ab 中提取值,并返回较小值对应的元素。
      4. boil 函数通过 reduce 方法遍历数组,应用比较函数,并最终返回单一的元素,即数组中的最小元素。如果数组为空或未定义,boil 函数返回 null
      5. min 函数最终返回 boil 函数的结果,即数组中的最小元素,如果数组为空,则返回 null

objectify:根据函数映射的键与值把数组转换为字典对象

  1. 使用说明
    • 参数:目标对象数组、条件函数1用于提取键、[条件函数2用于提取值]
    • 返回值:字典对象
  2. 使用代码示例
    import { objectify } from 'radash'
    
    const fish = [
      {
        name: 'Marlin',
        weight: 105
      },
      {
        name: 'Bass',
        weight: 8
      },
      {
        name: 'Trout',
        weight: 13
      }
    ]
    
    objectify(fish, f => f.name) // => { Marlin: [marlin object], Bass: [bass object], ... }
    objectify(
      fish,
      f => f.name,
      f => f.weight
    ) // => { Marlin: 105, Bass: 8, Trout: 13 }
    
  3. 源码解析
    // 定义一个泛型函数 `objectify`,它接受三个参数:
    // `array` 是一个具有只读属性的泛型数组,
    // `getKey` 是一个函数,用于从数组元素中提取键,
    // `getValue` 是一个可选的函数,用于从数组元素中提取值,默认情况下,它会返回元素本身作为值。
    export const objectify = <T, Key extends string | number | symbol, Value = T>(
      array: readonly T[],
      getKey: (item: T) => Key,
      getValue: (item: T) => Value = item => item as unknown as Value
    ): Record<Key, Value> => {
      // 使用数组的 `reduce` 方法来累积一个对象,该对象将数组元素映射为键值对。
      return array.reduce((acc, item) => {
        // 使用 `getKey` 函数从当前元素 `item` 中提取键,并使用 `getValue` 函数提取值。
        // 将这个键值对添加到累加器对象 `acc` 中。
        acc[getKey(item)] = getValue(item)
        // 返回更新后的累加器 `acc`。
        return acc
      }, {} as Record<Key, Value>) // 初始化累加器 `acc` 为一个空对象。
    }
    
    • 方法流程说明:
      1. 函数接收一个数组 array,一个 getKey 函数用于提取每个元素的键,以及一个可选的 getValue 函数用于提取每个元素的值。
      2. 如果没有提供 getValue 函数,则使用一个默认的函数,这个函数简单地将元素本身作为值。
      3. 使用 reduce 方法遍历数组。reduce 方法的累加器 acc 是一个对象,用于存储键值对。
      4. 对于数组中的每个元素 item,使用 getKey 函数提取键,并使用 getValue 函数提取值。
      5. 将提取的键和值作为一个键值对添加到累加器对象 acc 中。
      6. 继续处理数组的下一个元素,直到所有元素都被处理完毕。
      7. 返回累加器 acc,它现在是一个完整的对象,包含了从数组元素映射而来的键值对。

range:根据步长生成一个数值范围内的迭代值

  1. 使用说明
    • 参数:起始值、[结束值]、[迭代函数]、步长。
    • 返回值:用在for循环中循环输出处理的结果值。
  2. 使用代码示例
    import { range } from 'radash'
    
    range(3)                  // yields 0, 1, 2, 3
    range(0, 3)               // yields 0, 1, 2, 3
    range(0, 3, 'y')          // yields y, y, y, y
    range(0, 3, () => 'y')    // yields y, y, y, y
    range(0, 3, i => i)       // yields 0, 1, 2, 3
    range(0, 3, i => `y${i}`) // yields y0, y1, y2, y3
    range(0, 3, obj)          // yields obj, obj, obj, obj
    range(0, 6, i => i, 2)    // yields 0, 2, 4, 6
    
    for (const i of range(0, 200, 10)) {
      console.log(i) // => 0, 10, 20, 30 ... 190, 200
    }
    
    for (const i of range(0, 5)) {
      console.log(i) // => 0, 1, 2, 3, 4, 5
    }
    
  3. 源码解析
    // 定义一个泛型生成器函数 `range`,它接受一个默认类型参数 `T`,默认为 `number`。
    // 函数接受四个参数:起始值或长度 `startOrLength`,可选的结束值 `end`,
    // 可选的值或映射函数 `valueOrMapper` 用于生成序列中的值,以及可选的步长 `step`,默认为 1。
    export function* range<T = number>(
      startOrLength: number,
      end?: number,
      valueOrMapper: T | ((i: number) => T) = i => i as T,
      step: number = 1
    ): Generator<T> {
      // 确定 `valueOrMapper` 是一个函数还是一个固定值。如果是函数,则直接使用;如果不是,则创建一个总是返回该值的函数。
      const mapper = isFunction(valueOrMapper) ? valueOrMapper : () => valueOrMapper
      // 如果提供了 `end` 值,则 `start` 为 `startOrLength`;如果没有提供 `end` 值,则 `start` 默认为 0。
      const start = end ? startOrLength : 0
      // `final` 是序列的结束值,如果提供了 `end` 值,则使用它;如果没有,则 `final` 为 `startOrLength`。
      const final = end ?? startOrLength
      // 从 `start` 开始,到 `final` 结束,每次迭代增加 `step`。
      for (let i = start; i <= final; i += step) {
        // 使用 `yield` 关键字产生由 `mapper` 函数处理的当前迭代值 `i`。
        yield mapper(i)
        // 如果下一次增加步长后的值会超过 `final`,则提前终止循环。
        if (i + step > final) break
      }
    }
    
    • 方法流程说明:
      1. 确定 valueOrMapper 参数是一个函数还是一个值。如果是函数,直接用作映射器;如果是值,创建一个总是返回该值的函数作为映射器。
      2. 确定起始值 start。如果提供了 end 参数,startstartOrLength;否则 start 默认为 0。
      3. 确定结束值 final。如果提供了 end 参数,finalend;否则 finalstartOrLength
      4. 使用一个 for 循环从 start 遍历到 final,每次迭代增加步长 step
      5. 在每次迭代中,使用 yield 关键字来产出 mapper 函数处理过的当前值。
      6. 如果在下一次迭代步长加上当前值 i 会超过 final,则提前退出循环。
      7. 提示:这个 range 函数提供了类似于 Python 中的 range 函数的功能,允许在迭代中产生一系列的值。通过使用生成器,我们可以惰性地产生这些值,这意味着直到迭代器被消费时,这些值才会被计算和产生。这在处理大范围的值时非常有用,因为它不需要一次性将所有值加载到内存中。

replaceOrAppend:替换对象数组中的项或是追加项(条件函数不满足时追加);

  1. 使用说明

    • 参数:被替换数组、用来的替换的数组、条件函数。
    • 返回值:替换或者追加后的数组。
  2. 使用代码示例

    import { replaceOrAppend } from 'radash'
    
    const fish = [
      {
        name: 'Marlin',
        weight: 105
      },
      {
        name: 'Salmon',
        weight: 19
      },
      {
        name: 'Trout',
        weight: 13
      }
    ]
    
    const salmon = {
      name: 'Salmon',
      weight: 22
    }
    
    const sockeye = {
      name: 'Sockeye',
      weight: 8
    }
    
    replaceOrAppend(fish, salmon, f => f.name === 'Salmon') // => [marlin, salmon (weight:22), trout]
    replaceOrAppend(fish, sockeye, f => f.name === 'Sockeye') // => [marlin, salmon, trout, sockeye]
    
  3. 源码解析

    // 定义一个泛型函数 `replaceOrAppend`,它接受三个参数:
    // `list` 是一个具有只读属性的泛型数组,
    // `newItem` 是一个新的元素,将被添加到数组中,
    // `match` 是一个函数,用于确定新元素应该替换数组中的哪个现有元素。
    export const replaceOrAppend = <T>(
      list: readonly T[],
      newItem: T,
      match: (a: T, idx: number) => boolean
    ) => {
      // 如果 `list` 和 `newItem` 都不存在或为空,则返回一个空数组。
      if (!list && !newItem) return []
      // 如果 `newItem` 不存在或为空,则返回 `list` 数组的副本。
      if (!newItem) return [...list]
      // 如果 `list` 不存在或为空,则返回一个只包含 `newItem` 的数组。
      if (!list) return [newItem]
      // 遍历 `list` 数组,寻找一个匹配的元素。
      for (let idx = 0; idx < list.length; idx++) {
        const item = list[idx]
        // 如果 `match` 函数返回 `true`,则在该位置替换元素。
        if (match(item, idx)) {
          // 创建一个新数组,其中包含从 `list` 开始到匹配位置之前的所有元素,
          // 然后是 `newItem`,然后是从匹配位置之后到 `list` 结束的所有元素。
          return [
            ...list.slice(0, idx),
            newItem,
            ...list.slice(idx + 1, list.length)
          ]
        }
      }
      // 如果没有找到匹配的元素,将 `newItem` 追加到 `list` 数组的末尾。
      return [...list, newItem]
    }
    
    • 方法流程说明:
      1. 进行一系列的检查,如果 listnewItem 都不存在或为空,或者只有 newItem 不存在或为空,或者只有 list 不存在或为空,则返回相应的结果。
      2. 如果 listnewItem 都存在,遍历 list 数组,对于每个元素和它的索引,调用 match 函数。
      3. 如果 match 函数对某个元素返回 true,说明找到了应该被替换的元素。函数将创建一个新数组,该数组由以下部分组成:从 list 的开始到匹配元素之前的部分,newItem,以及从匹配元素之后到 list 结尾的部分。
      4. 如果遍历完成后没有找到任何匹配的元素,函数将 newItem 添加到 list 的末尾,并返回新数组。

下期我们将介绍 radash 中剩余的数组相关方法

  • replace :查找指定项,并用传入的去替换;
  • select :对数组同时进行过滤和映射,输出映射后的value数组;
  • shift :把目标数组向右移动 n 个位置返回为一个新数组;
  • sift:过滤调列表中值为false的项,返回剩余为true的项组成的数组;
  • sort :把数组按照条件函数指定的项的数值大小排序,支持升序和降序;
  • sum:数组对象根据条件函数指定想的数组求和;
  • toggle:查找数组中是否有我们给定的项,有则删除,没有则添加;
  • unique:数组去重,去除数组中重复的项;
  • zipToObject:将第一个数组中的键映射到第二个数组中对应的值;
  • zip:把两个数组变为二维数组,二维数组中的每个数组包含两个项分别为两个传入数组的相同位置的项。

写在后面

  • 后续作者会整理一份radash完整方法目录上传,方便没法访问外网的朋友查看使用。
  • 下期方法分享完后,会同步整理分享Array方法的使用说明目录,方便大家查阅对照使用。
  • 小tips:不出意外的话博主每周五会定时更新,出意外的话就是出意外了。
  • 大家有任何问题或见解,欢迎评论区留言交流和批评指正!!!
  • 点击访问:radash官网

标签:const,函数,name,元素,list,已死,源码,数组,lodash
From: https://www.cnblogs.com/muqiqiang/p/18130765

相关文章

  • hashMap源码分析
    先分析hashMap的put方法:当执行put操作时会调用底层的putVal方法,以下是这个方法的分析执行Put方法时会先判断当前哈希表是否为空,为空则先扩容,然后计算出hash值对应的索引,判断索引位置上的节点是否为空,空则插入这个新节点。否则便要判断节点上的key是不是和原先的key相同,相同则进行......
  • Flink源码学习(4) TaskManager从节点启动分析
    taskManager是flink的worker节点,负责slot的资源管理和task执行一个taskManager就是一台服务器的抽象TaskManager基本资源单位是slot,一个作业的task会部署在一个TM的slot上运行,TM会负责维护本地的slot资源列表,并与Master和JobManager进行通信启动主类:TaskManagerRunnerTaskMan......
  • 基于dremio 安装包进行源码依赖包maven 私服重建的一个思路
    dremio25.0版本已经发布了,但是如果希望自己源码构建,但是缺少一些依赖造成编译会有问题,但是我们可以直接基于官方提供的下载包的文件进行maven私服的重建,以下说明下简单流程参考流程下载软件包这个可以从dremio官网下载到最好选择一个可以构建的分支本地构建下此步......
  • python计算机毕设【附源码】养老院管理系统(django+mysql+论文)
    本系统(程序+源码)带文档lw万字以上  文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:随着社会的快速发展,人口老龄化问题日益凸显。养老院作为为老年人提供居住、医疗、康复、娱乐等综合服务的场所,其管理水平和服务质量对老年人的生活质量有着......
  • java+saas模式医院云HIS系统源码Java+Spring+MySQL + MyCat融合BS版电子病历系统,支持
    java+saas模式医院云HIS系统源码Java+Spring+MySQL+MyCat融合BS版电子病历系统,支持电子病历四级云HIS系统是一款满足基层医院各类业务需要的健康云产品。该产品能帮助基层医院完成日常各类业务,提供病患预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医......
  • Dubbo源码解读-Consumer消费端@Reference服务端引用流程
    上篇我们介绍了Provider端监听注册中心动态配置原理,地址如下Dubbo源码解析-Provider端监听注册中心动态配置原理-CSDN博客    本文主要针Dubbo消费端@Reference服务端引用流程原理,从dubbo源码角度进行解析。    大家可以好好仔细读一下本文。有疑问欢迎留言......
  • 青否科技为什么要开发数字人直播源码!
    直播作为一种新的电商形态,电商直播化与直播电商化的现象已经逐渐普遍。数字人从去年双11作为集团十大黑科技正式公开亮相,该产品从以前的窗口式问答,升级为直播间的多维度互动,技术不断在进步!我们知道去年双11它最大的变化来自于一天变成了两个时段。同时,直播带货的GMV在整个电商场......
  • 【附源码】JAVA计算机毕业设计小型家政服务管理系统的设计与实现(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着社会的快速发展和人们生活节奏的加快,家政服务行业应运而生,并迅速发展壮大。越来越多的家庭开始聘请家政人员来帮助处理家庭日常事务,如清洁、烹饪、......
  • java计算机毕业设计基于微信小程序的书籍销售系统【附源码+远程部署+程序+mysql】
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着移动互联网技术的飞速发展,智能手机用户数量急剧增加,人们获取信息和进行日常交易的方式正逐步向移动端转移。微信作为中国最流行的社交通讯软件,其推出......
  • 企业工程项目管理系统源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管
     工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理   工程项目各模块及其功能点清单一、系统管理    1、数据字典:实现对数据字典标签的增删改查操......