掌握 NumPy:高效数组处理综合指南(第 1/2 部分)

news2024/10/7 12:17:45

掌握 NumPy:高效数组处理综合指南(第 1/2 部分)

文章目录

  • 一、介绍
  • 二、什么是Numpy,我们为什么要使用它?
  • 三. 数组初始化
  • 四. 计算速度和内存使用量
  • 五、内存使用情况
  • 六、数据类型
  • 七、索引和切片

一、介绍

你们以前听说过 NumPy 吗?好吧,你可能有,也许你甚至在你的许多项目中使用过它。就我而言,我第一次使用它是在我开始学习机器学习的时候。然而,当时我只使用了基本函数,即数组初始化、数学运算等。直到我意识到深入研究 Numpy 本身的好处,我才开始探索有关该主题的各种 YouTube 教程和电子书。令我惊讶的是,实际上有许多我希望我早点知道的 Numpy 功能。

二、什么是Numpy,我们为什么要使用它?

在我们进入代码之前,我想先谈谈这个模块。Numpy 代表 Numerical Python,基本上是一个开源 Python 模块,允许我们处理数字和多维数组。与标准 Python 列表相比,使用此模块至少可以获得 3 个优势。首先,在数值计算和数组操作方面,它提供了更大的灵活性。第二,Numpy 速度更快,第三,它消耗的内存更少。最后提到的两个优点基本上是因为 Numpy 的大多数后端都使用 C 编程语言 [1]。

在这篇文章中,我将为想要从一开始就学习Numpy的你写一个分步指南。本文分为几个章节,列出如下:

Numpy 安装
数组初始化
Numpy 数组限制
计算速度和内存使用率
数据类型
索引和切片
数组生成函数
随机数
查看和复制
数学函数
逻辑运算符和按位运算符
搜索和排序
塑造和重塑
串联和拆分
事不宜迟,让我们现在亲自动手使用代码吧!

注意:本文中使用的所有资源都可以在我的 GitHub 存储库中找到。 这是它的链接。

  1. Numpy 安装
    安装 Numpy 非常简单,您只需在笔记本电脑或命令提示符下运行即可。就我而言,图 1 中的文本出现,因为该模块已经正确安装。
    pip install numpy
# Codeblock 1
! pip install numpy

图 1.如果我们尝试在已经安装了模块的环境中安装 Numpy,输出会是什么样子。
安装完成后,我们可以通过运行 来导入它。当这段代码运行时,现在我们可以说这是 Nupy 的别名。好吧,从技术上讲,实际上可以为 Nupy 创建任何别名。但我建议你不要这样做,因为它可能会让你将来感到困惑。接下来,要检查当前的 Numpy 版本,我们可以直接打印出 的属性。如下图所示,我在本教程中使用的 Numpy 版本是 1.25.0。如果您的版本不同,请不要担心,因为我认为一个版本和另一个版本之间没有太大区别。但是,如果您不确定,可以使用 .import numpy as npnp__version__nppip install numpy==1.25.0

# Codeblock 2
import numpy as np
np.__version__

在这里插入图片描述

图2.我在本教程中使用的 Numpy 版本。

三. 数组初始化

我想谈的第一个 Numpy 函数是用于初始化数组的函数,即 。要使用此函数,我们可以简单地传递输入列表。或者,您也可以用来做同样的事情。嗯,和 之间实际上有细微的区别。但是,您现在可以忽略它。np.array()np.asarray()np.array()np.asarray()

# Codeblock 3
np.array([7,6,5,4,3,2])

### Alternative
# np.asarray([7,6,5,4,3,2])

在这里插入图片描述

图3.代码块 3.
运行上述代码时,它将返回一个输出,如图 3 所示。如果将该数组放在函数中,则输出看起来会有所不同。在下图中,您可以看到文本“数组”以及逗号消失了。然而,请记住,这实际上只是代表的问题。print()

# Codeblock 4
print(np.asarray([7,6,5,4,3,2]))

在这里插入图片描述

图4.如果我们使用 print() 显示数组,它会是什么样子。
上面的行为实际上与Python列表不同。如果我们尝试将其打印出来,无论使用函数如何,结果都将如图 5 所示。我们可以在图中看到,所有元素都用逗号分隔,同时没有打印“数组”文本。print()

# Codeblock 5
[7,6,5,4,3,2]

### Returns the exact same result.
# print([7,6,5,4,3,2])

在这里插入图片描述

图5.标准 Python 列表是什么样子的。
当我们尝试打印出 2D 数组时,也可以看到 Numpy 数组和 Python 列表之间的另一个区别。您可以在下面看到 Numpy 数组自动打印为行和列,而 Python 列表则不是。

# Codeblock 6
print(np.asarray([[7,6,5,4,3,2], 
                  [9,8,7,6,5,4]]), end='\n\n')

print([[7,6,5,4,3,2], 
       [9,8,7,6,5,4]])

在这里插入图片描述

图6.以 Numpy 数组(上图)和 Python 列表(下图)的形式显示 2D 数组。
两者都用于将列表转换为 Numpy 数组。要反之亦然,我们可以使用该方法。请参阅下面的代码块 7。np.array()np.asarray()tolist()

# Codeblock 7
A = [2,4,6,8]
B = np.array(A)   # Convert to Numpy array.
C = B.tolist()    # Convert to Python list.

print(B)
print(C)

在这里插入图片描述

图7.可以使用 np.array() 和 tolist() 完成两种数组类型之间的转换。
如果您不确定变量是否包含列表或 Numpy 数组,我们可以使用该函数进行检查,而无需显示该变量的全部内容。在 Codeblock 8 中,我在 和 上使用该函数。顺便说一句,结果输出中的术语“ndarray”基本上代表 N 维数组。type()ABC

# Codeblock 8
print('type(A):', type(A))
print('type(B):', type(B))
print('type(C):', type(C))

在这里插入图片描述

图8.A、B 和 C 的对象类型。
在本章中,我想向您展示的最后一件事是,我们可以根据 txt 文件中的数据自动初始化 Numpy 数组。我们可以为此使用的函数是 。举个例子,下面是文件内容的样子,我们将使用 Codeblock 9 中的代码加载它。在这里,我将参数设置为(逗号)。您可能需要根据 txt 文件中一个数字与另一个数字的分离方式进行更改。np.genfromtxt()data.txtdelimiter,

在这里插入图片描述

图 9.数据将加载为 Numpy 数组的 txt 文件。

# Codeblock 9
np.genfromtxt('data.txt', delimiter=',')

在这里插入图片描述

图 10.data.txt已使用 np.genfromtxt() 成功加载为 Numpy 数组。
3. Numpy 数组限制
在我们讨论使用 Nupy 可以完成的所有事情之前,我将告诉您该模块不能做什么。在下面的 Codeblock 10 中,我将多个不同数据类型的值放在 Python 列表中,该列表似乎能够正确处理这些值。

# Codeblock 10
D = [2, 'Hello', True, 9.886]
D

在这里插入图片描述
在这里插入图片描述

图 11.列表 D 同时包含整数、字符串、布尔值和浮点数数据类型。
如果我们将 list 转换为 Numpy 数组,即使我们再次将其转换回 list,里面的所有值也会自动变成字符串。D

# Codeblock 11
print(np.array(D))
print(np.array(D).tolist())

图 12.Numpy 将列表 D 的所有元素设置为字符串。
上面的演示基本上表明了使用 Numpy 数组的缺点:它无法存储多个数据类型的元素。然而,这种行为背后实际上是有原因的,与 Python 列表相比,它允许数组计算更快且内存效率更高。我将在下一章中证明这个概念。

四. 计算速度和内存使用量

为了查看 Numpy 数组和 Python 列表执行完全相同的操作所需的时间,我们需要导入模块并初始化要使用的数组。time

# Codeblock 12
import time

E = [123] * 9999999
F = np.array(E, dtype='int8')

这个实验的想法非常简单,我想做的就是使用 和 对列表和数组中的所有值求和。之后,我将打印出计算时间。我在下面写的两个函数,即使用 Python 函数的函数,而使用 .EFsum()np.sum()summation_python_sum()sum()summation_numpy_sum()np.sum()

# Codeblock 13
def summation_python_sum(arr):
    start_time = time.time()
    sum(arr)
    end_time = time.time()

    total_time = end_time - start_time
    return total_time
    
def summation_numpy_sum(arr):
    start_time = time.time()
    np.sum(arr)
    end_time = time.time()

    total_time = end_time - start_time
    return total_time

由于上面的两个函数已经声明,现在我们可以通过运行下面的代码块 14 来开始我们的实验。

# Codeblock 14
print('Python list with sum()\t\t: ', summation_python_sum(E), 'sec')
print('Python list with np.sum()\t: ', summation_numpy_sum(E), 'sec')
print('Numpy array with sum()\t\t: ', summation_python_sum(F), 'sec')
print('Numpy array with np.sum()\t: ', summation_numpy_sum(F), 'sec')

在这里插入图片描述

图 13.Python list 和 Numpy 数组以及 sum() 和 np.sum() 函数之间的运行时间比较。
根据上面的结果,我们可以看到 Numpy 数组的工作速度比其他数组快得多,尤其是当它与 Numpy 函数配对时(0.01 秒)。当使用 Python 函数执行 Python 列表时,获得第二快的结果(0.09 秒)。但是,在这种情况下,它仍然比 Numpy 慢 9 倍左右。我们需要注意的一件事是,我认为我们应该避免将 Python 函数与 Numpy 数组混合使用,或者将 Python 列表与 Numpy 函数混合使用,因为这会导致处理时间变得更慢。

五、内存使用情况

这就是计算速度,现在让我们看看列表和数组占用多少内存。我们可以通过执行下面的代码块来做到这一点。EF

# Codeblock 15
import sys

print('E (Python list):', sys.getsizeof(E), 'bytes')
print('F (Numpy array):', sys.getsizeof(F), 'bytes')

在这里插入图片描述

图 14.E 和 F 使用的内存量。
如上所示,与数组相比,list 占用的内存是数组的 8 倍。您可能已经注意到,在代码块 12 中,我用于参数,它本质上代表 8 位整数。在这种情况下,我决定只使用 8 位,因为我们数组中的数字非常小。Numpy 确实允许我们在数据类型中指定此类细节,使其在内存使用方面更有效率。我们将在第 5 章中更深入地了解 Numpy 数据类型。EFint8dtype

六、数据类型

我们可以通过打印出 Numpy 数组的属性来检查它的数据类型。在下面的输出中,我们可以看到数组的数据类型是 ,这与我们之前设置的完全相同。同时,请记住,以前我们没有指定数组的数据类型。在这种情况下,Numpy 通常会将其设置为 。dtypeFint8Bint32

# Codeblock 16
print(B.dtype)
print(F.dtype)

在这里插入图片描述

图 15.数组 B 和 F 的数据类型。
我经常使用的其他数组数据类型是 float 和 boolean。在 float 的情况下,您只需将非整数数组传入其中,它就会自动将数据类型设置为 。np.array()float64

# Codeblock 17
print(np.array([5, 5, 5, 5.3, 5]).dtype)
print(np.array([True, True, False]).dtype)

在这里插入图片描述

图 16.代码块 17 中两个数组的数据类型。
Integer 和 Float 数据类型
现在我想更深入地谈谈整数和浮点数。正如我之前提到的,写在后面的数字基本上表示用于表示整数值的位数。让我们看一下这个例子:假设我们有数字 26。在二进制中,26 等价于 11010,其中它使用 5 个二进制数字表示,即 5 位。如果我们将这个数字存储到具有数据类型的 Numpy 数组中,则该数字将存储为 00011010。intint8

00011010本身的二进制序列基本上仍然等价于 26,只是它现在以 8 位表示。如果改用,则该数字将写为 00000000 00011010。根据这一事实,它现在感觉到,即使存储的数字保持不变,更多的位也需要更多的内存。int16

此外,您还需要知道,较小的位数会导致我们的数字范围更有限。可以存储的最大和最小数量分别为 127 和 -128。第一个数字用于表示符号(即正数或负数),而其余数字则负责存储幅度。同时,在浮点数的情况下,较小的位使得要存储的数字具有较低的精度。int8

我们可以使用以下代码查看每个整数数据类型的详细信息。

# Codeblock 18
print(np.iinfo(np.int8))
print(np.iinfo(np.int16))
print(np.iinfo(np.int32))
print(np.iinfo(np.int64))

在这里插入图片描述

图 17.可以通过 np.iinfo() 函数查看每个整数数据类型的最大值和最小值。
对于浮点数据类型,也可以使用 获得类似的信息。np.finfo()

# Codeblock 19
print(np.finfo(np.float16))
print(np.finfo(np.float32))
print(np.finfo(np.float64))

在这里插入图片描述

图 18.Numpy 中每个浮点数据类型的详细信息。
不仅是布尔值、整数和浮点数,实际上还有很多其他数据类型我没有解释。如果你有兴趣了解更多信息,你可以通过这个链接[2]访问Numpy关于数据类型的文档。

七、索引和切片

在许多情况下,对 Numpy 数组进行索引和切片类似于 Python 列表。为了演示这一点,让我们考虑以下数组。

# Codeblock 20
G = np.array([9, 7, 5, 6, 4, 8, 2, 6, 9, 5, 2, 4, 1, 4])

我将在 Codeblock 21 中对数组执行各种索引和切片技术。G

# Codeblock 21
print('G[7]\t\t:', G[7])        #(1)
print('G[-2]\t\t:', G[-2])      #(2)
print('G[:3]\t\t:', G[:3])      #(3)
print('G[3:]\t\t:', G[3:])      #(4)
print('G[2:6]\t\t:', G[2:6])    #(5)
print('G[1:7:2]\t:', G[1:7:2])  #(6)
print('G[::3]\t\t:', G[::3])    #(7)

以下是上述代码的实际作用:

G[7]→ 取数组 G 的第 7 个元素。
G[-2]→ 从后面拿第二个元素。
G[:3]→ 取前 3 个元素。
G[3:]→ 取除前 3 个元素以外的所有元素。我们将从一路开始到结束。请记住,数组索引从 0 开始。G[3]
G[2:6]→ 从索引 2 到 5 中取元素(不包括索引 6)。
G[1:7:2]→ 以 2 为步长从索引 1 到 6 取元素。
G[::3]→ 在第 3 步中获取所有元素。
以下是 Codeblock 21 的输出如下所示:

在这里插入图片描述

图 19.代码块 21 的输出。
上面关于索引和切片的演示也可以在 Python 列表上实现。实际上,有一种技术专门适用于 Numpy 数组:使用另一个数组进行索引。在下面的示例中,我们从数组中获取索引 6、4、5、7 和 3 的值。G

# Codeblock 22
H = np.array([6,4,5,7,4,3])
print('G[H]\t:', G[H])

在这里插入图片描述

图 20.将一个数组与另一个数组建立索引。
多维数组
在索引和切片方面,Numpy 数组优于 Python 列表的优势可以清楚地看到,尤其是当我们使用多维数组时。本章中的以下示例不适用于列表。

现在让我们先初始化一个 2D 数组。

# Codeblock 23
I = np.array([[3, 1, 5, 7], 
              [2, 5, 3, 2], 
              [3, 8, 5, 9],
              [4, 8, 2, 6]])

二维数组实际上可以被看作是一个矩阵。在本例中,矩阵的大小为 4×4(4 行和 4 列)。该矩阵如下面的图 21 所示。I

在这里插入图片描述

图 21.以矩阵形式可视化的 I 数组。
为了获取第 0 行和第 2 列(数字 5),我们可以使用 Codeblock 24 中的代码。这个想法很简单,我们需要做的就是写下要选择的行号和列号。

# Codeblock 24
I[0,2]

在这里插入图片描述

图 22.代码块 24.
接下来,我们可以使用 Codeblock 25 获取前 2 行和前 3 列。

# Codeblock 25
I[:2,:3]

在这里插入图片描述

图 23.使用 Codeblock 25 选择的元素。
如果要获取整行或整列,只需使用 .在下面的示例中,我想做的是将第 1 列的整行取到 3 列(不包括第三个索引)。:

# Codeblock 26
I[:,1:3]

在这里插入图片描述

图 24.取第 1 列和第 2 列的整行。
以下示例与上一个示例类似,只是此处我们排除最后一行。

# Codeblock 27
I[:-1,1:3]

在这里插入图片描述

图 25.与图 24 类似,但此处不采用最后一行。
使用另一个数组或列表进行索引也适用于 2D 数组。在下面的示例中,我从第 0 行和第 2 行中选取前 3 列。

# Codeblock 28
I[[0,2], :3]

在这里插入图片描述

图 26.仅从第 0 行和第 2 行中获取前 3 列的值。
最后,下面是当我们同时从“坐标”中获取元素时的结果。[0,0][1,1][2,2]

# Codeblock 29
I[[0,1,2], [0,1,2]]

在这里插入图片描述

图 27.与图 26 类似,不同之处在于这里我们指定了要手动获取的两个轴的索引。
7. 数组生成函数
Numpy 允许我们轻松生成特定数字的数组。我将从 和 开始。这些函数的使用方式基本相同,只是前者生成一个包含 1 的数组,而后者生成一个填充 0 的数组。我们需要做的就是为参数指定所需的形状。在 Codeblock 30 中,我演示了如何使用 np.ones() 创建由 10 个元素组成的一维数组。np.ones()np.zeros()

# Codeblock 30
np.ones(10)

在这里插入图片描述

图 28.使用 np.ones() 创建的一维数组。
若要创建二维数组,参数需要采用元组形式。在这里,我创建了具有 4 行和 3 列的全零数组。

# Codeblock 31
np.zeros((4,3))

在这里插入图片描述

图 29.使用 np.zeros() 创建的形状为 4×3 的 2D 数组。
不仅是一维和二维的,而且两者兼而有之,还允许我们创建更大维度的数组。在下面的例子中,我们可以将其视为四个 2D 数组,其中每个数组由 5 行和 6 列组成。np.ones()np.zeros()

# Codeblock 32
np.zeros((4,5,6))

在这里插入图片描述

图 30.四个 2D 阵列,每个阵列的大小为 5×6。
如果您熟悉矩阵,您可能经常听到“单位矩阵”一词。Numpy 提供了一个函数来通过 创建这种矩阵。在代码块 33 中,我创建了一个大小为 6×6 的单位矩阵。np.identity()

# Codeblock 33
np.identity(6)

在这里插入图片描述

图 31.使用 np.identity() 创建恒等矩阵。
请记住,这只能形成一个方阵。如果您需要创建一个具有更多灵活性的类似版本,则可以使用。 允许我们控制矩阵的高度 () 和宽度 () 以及对角线 () 的偏移量。在随后的示例中,我将矩阵大小设置为 6×4,对角线偏移量为 1(这意味着矩阵向右移动一次)。np.identity()np.eye()np.eye()NMk

# Codeblock 34
np.eye(N=6, M=4, k=1)

在这里插入图片描述

图 32.使用 np.eye() 构造的矩阵。
np.diag()另一方面,创建一个数组,可以手动定义对角线中的元素。也可以将该参数用于此函数。k

# Codeblock 35
np.diag([1,4,3,4,4])

在这里插入图片描述

图 33.使用 .np.diag()
接下来我要给大家看的是。实际上,我发现这个函数很有趣,因为生成的输出看起来像一个随机值。事实上,它并不是为了生成随机数,而是基本上采用当前内存状态的值。如果您想分配一个空数组以供稍后填充,但您非常关心计算时间,则此方法非常有用。根据我的实验,比两者都慢得多。 本身确实比 .np.empty()np.ones()np.zeros()np.empty()np.empty()np.zeros()

# Codeblock 36
np.empty((3,3))

在这里插入图片描述

图 34.由 np.empty() 生成的 3×3 数组。
如果您需要一个具有与 相似行为的函数,但具有您可以自行指定的数字,则可以使用 .随后的代码块显示了我如何使用该函数创建一个大小为 3×5 的数组,其中的元素都是 999。np.zeros()np.ones()np.full()

# Codeblock 37
J = np.full(shape=(3,5), fill_value=999)
J

在这里插入图片描述

图 35.创建一个所有元素均为 999 的数组。
如果您需要创建一个由特定数字组成的数组,同时您还希望它具有与另一个现有数组相同的形状,则可以使用 、 或 。好吧,一开始听起来可能有点令人困惑,但一旦你看到下面的例子,你就会明白。np.full_like()np.empty_like()np.ones_like()np.zeros_like()

# Codeblock 38
np.full_like(J, fill_value=111)

在这里插入图片描述

图 36.创建形状与数组 J 完全相同的 all-111 数组。
在上面的例子中,采用数组的形状,即 。然后,它将所有元素的值设置为 111。类似的事情也适用于其他三个函数,只是我们不需要使用参数。如图 37 中的输出所示,所有生成的数组都具有与 相同的形状。np.full_like()J(3,5)fill_valueJ

# Codeblock 39
print(np.empty_like(J), end='\n\n')
print(np.ones_like(J), end='\n\n')
print(np.zeros_like(J))

在这里插入图片描述

图 37.由 np.ones_like()、np.zeros_like() 和 np.empty_like() 生成的数组。
序号
现在让我们讨论如何使用 Numpy 创建序列号数组。用于此目的的第一个函数是 。这个函数其实类似于 Python 的 .两者的不同之处在于自动生成数组,而 while 是迭代器。下面的代码块 40 显示了如何使用创建包含数字 0 到 19 的数组。np.arange()range()np.arange()range()np.arange()

# Codeblock 40
np.arange(20)

在这里插入图片描述

图 38.使用 np.arange() 创建序列号。
为了使用 创建相同的东西,我们需要这样写下来:range()

# Codeblock 41
[i for i in range(20)]

在这里插入图片描述

图 39.使用 range() 生成相同的数字序列。
尽管行为存在这种差异,但可设置的参数完全相同,分别是 、 和 。请记住,我们为停靠点指定的编号不会包含在序列中。以下代码块显示了如何使用 .startstopstepnp.arange()

# Codeblock 42
print(np.arange(3, 20, 2), end='\n\n')
print(np.arange(100, 0, -3), end='\n\n')
print(np.arange(20, 30, 0.5))

在这里插入图片描述

图 40.np.arange() 生成的数字序列。
事实上,该函数有一个优点:它允许我们将浮点数传递给参数,就像我在 Codeblock 42 的最后一个示例中所做的那样。np.arange()range()

另一个生成序列号的 Numpy 函数基本上代表线性空间。此函数的前两个参数是 和 ,就像 一样。但是,第三个是不同的,它用于控制我们想要生成的元素数量。在下面的示例中,我将函数设置为写入 50 个数字,从 1 到 15 均匀延伸。请注意,参数 的行为与 不同,从某种意义上说,传入它的数字包含在数组中。np.linspace()startstopnp.arange()np.linspace()numstopnp.linspace()np.arange()

# Codeblock 43
np.linspace(1, 15, 50)

在这里插入图片描述

图 41.由 np.linspace() 生成的数组。所有这些数字都是均匀延伸的。
有一个类似的函数,我实际上从未使用过。数字的分布不是遵循线性比例,而是遵循几何比例。以下是如何使用该函数的示例。np.geomspace()

# Codeblock 44
np.geomspace(1, 15, 50)

在这里插入图片描述

图 42.请注意,np.geomspace() 生成的数字与 np.linspace() 不同。
未完待续
在这一点上,我才意识到这篇文章已经达到了 17 分钟的阅读时间,我想这对于一篇文章来说太长了。所以,我决定继续另一个。下期见!

引用
[1] 从源代码构建。NumPy的。https://numpy.org/doc/stable/user/building.html [2024年1月4日访问]。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1849486.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

连接和断开信号演示之二

代码; #include <gtk-2.0/gtk/gtk.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <glib-2.0/glib.h> #include <stdio.h>void button_press(GtkEventBox *ebox,GdkEventButton *event,GtkLabel *label) {const char *citem;switch(event->type…

[图解]建模相关的基础知识-15

1 00:00:01,030 --> 00:00:05,820 接下来&#xff0c;我们就开始讲解的知识点 2 00:00:05,830 --> 00:00:11,810 就是范式知识点 3 00:00:12,130 --> 00:00:17,490 关系这个理论里面&#xff0c;随着历史的发展 4 00:00:17,700 --> 00:00:21,280 它发展出很多的…

力扣随机一题 模拟+字符串

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 1910.删除一个字符串中所有出现的给定子字符串【中等】 题目&#xff1a; …

基于STM32的智能工厂环境监测系统

目录 引言环境准备智能工厂环境监测系统基础代码实现&#xff1a;实现智能工厂环境监测系统 4.1 数据采集模块4.2 数据处理4.3 控制系统实现4.4 用户界面与数据可视化应用场景&#xff1a;智能工厂管理与优化问题解决方案与优化收尾与总结 1. 引言 智能工厂环境监测系统通过…

【转】FreeRTOS通用移植,以keil和IAR工程 M7核为例

目录 keil: IAR keil: 原文在https://bbs.eeworld.com.cn/thread-1281875-1-1.html 本篇讲述移植FreeRTOS,并创建运行一个任务&#xff0c;对象芯片为M7系列的兆易创新GD32H7xx系列。 一.准备工作 1.下载FreeRTOS源码官网 http://www.freertos.org/ 或者托管网站FreeRTOS…

Vue71-嵌套(多级)路由

一、需求 二、开发步骤 2-1、编写路由组件 2-2、编写路由规则 2-3、编写路由标签<router-link>、<router-view> 三、小结

(vue3)基于vite+vue3+element-plus项目创建

(vue3)基于vitevue3element-plus项目创建 vue.js官方中文文档&#xff1a;https://cn.vuejs.org/guide/quick-start.html vite官方中文文档&#xff1a;https://cn.vitejs.dev/guide/ element-plus官网&#xff1a;https://element-plus.org/zh-CN/guide/installation.html 第…

Github 2024-06-19 C开源项目日报 Top9

根据Github Trendings的统计,今日(2024-06-19统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目9C++项目1Netdata: 开源实时监控平台 创建周期:4020 天开发语言:C协议类型:GNU General Public License v3.0Star数量:68982 个Fork数量…

echarts实现折线图点击添加标记

文章目录 背景一、代码示例 背景 业务场景体现在功能层面主要两点&#xff0c; 折线图表设置点击事件点击事件与图标渲染标记绑定 对于节点没有被添加标记的可以&#xff0c;弹框提示添加标记&#xff0c;并提供标记内容输入框&#xff0c;已经添加过标记的点&#xff0c;点…

python pynput实现鼠标点击两坐标生成截图

脚本主要实现以下功能&#xff1a; 按ctrl开始截图&#xff0c;点击两个坐标&#xff0c;保存截图tk输出截图文本信息&#xff0c;文本输出内容倒序处理默认命名为A0自增。支持自定义名称&#xff0c;自增编号&#xff0c;修改自定义名称自增重新计算清空文本框内容 from pyn…

笨蛋学算法之LeetCodeHot100_5_三数之和(Java)

package com.lsy.leetcodehot100;import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class _Hot6_三数之和 {public static List<List<Integer>> threeSum(int[] nums) {//先排序数组Arrays.sort(nums);//存放结果集List<Lis…

超强开源全能日程助手—揭秘FullCalendar

引言 FullCalendar 是一个广受欢迎的开源 JavaScript 库&#xff0c;用于在网页上展示和管理事件和日程。 它最初是基于 jQuery 开发的&#xff0c;但随着时间的推移&#xff0c;经过 v1~v6 版本的迭代后&#xff0c;它已经全面支持React、Vue 和 Angular 的版本。FullCalend…

【ARMv8/v9 GIC 系列 2.2 -- GIC SPI 中断的 GICD_ISACTIVER 和 GICD_ICACTIVER 配置】

文章目录 GIC 中断 Active 状态的配置中断状态分类GICD_ISACTIVER<n>GICD_ICACTIVER<n>参数 n 编号解释中断设置举例设置中断ID 68为活动状态清除中断ID 68的活动状态 小结 GIC 中断 Active 状态的配置 在ARMv8/ARMv9 体系结构中&#xff0c;GICD_ISACTIVER<n&…

2024年全国青少信息素养大赛python编程复赛集训第四天编程题分享

整理资料不容易,感谢各位大佬给个点赞和分享吧,谢谢 大家如果不想阅读前边的比赛内容介绍,可以直接跳过:拉到底部看集训题目 (一)比赛内容: 【小学组】 1.了解输入与输出的概念,掌握使用基本输入输出和简单运算 为主的标准函数; 2.掌握注释的方法; 3.掌握基本数…

【一步一步了解Java系列】:认识异常类

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 个人主页&#xff1a;Gu Gu Study专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1a;小闭…

qt开发-09_分裂器

QSplitter 是 Qt 框架中的一个非常实用的控件&#xff0c;用于创建可调整大小的窗格。它允许用户通过拖动子窗口间的边界&#xff08;也称为分割条&#xff09;来动态调整子窗口的尺寸。这在开发需要多个视图同时显示&#xff0c;且用户需要根据需要调整每个视图大小的应用程序…

pdf只要其中一页,pdf只要其中几页怎么弄

在现代办公和学习环境中&#xff0c;pdf文件因其跨平台、保持原样等优点而被广泛使用。然而&#xff0c;有时我们需要一个pdf其中页或其中几页&#xff0c;以便更好地管理和使用其中的内容。本文将详细介绍几种拆分pdf文件的方法&#xff0c;帮助您轻松应对各种拆分需求。 打开…

【LeetCode:2663. 字典序最小的美丽字符串 + 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Qt creator day3练习

2、升级优化自己应用程序的登录界面。 要求&#xff1a; 1. qss实现 2. 需要有图层的叠加 &#xff08;QFrame&#xff09; 3. 设置纯净窗口后&#xff0c;有关闭等窗口功能。 4. 如果账号密码正确&#xff0c;则实现登录界面关闭&#xff0c;另一个应用界面显示。 widget…

架构师指南:现代 Datalake 参考架构

这篇文章的缩写版本于 2024 年 3 月 26 日出现在 The New Stack 上。 旨在最大化其数据资产的企业正在采用可扩展、灵活和统一的数据存储和分析方法。这一趋势是由企业架构师推动的&#xff0c;他们的任务是制定符合不断变化的业务需求的基础设施。现代数据湖体系结构通过将数…