判断是否是数值的几种不同方式的效率比较

本文对比了在Chrome浏览器中使用正则表达式、instanceof Number、constructor和toStr.call方法来判断数值类型的效率。

今天针对不同的数值判定方式在chrome上做了一个效率的对比,结果如下:

注意:通过正则表达式仅能用于字符串中的内容是否是纯数值,而不能用于判断是否是数值对象。放在此处仅用于对比。


其代码如下:

		var ret;
		var o = 1;
		var pattern = /^(-?\d*.?\d*)$/;
		var toStr = {}.toString;
		var array = {};
		array["[object Number]"] = "number";
		
		console.log("各种判断是否数值的速度比较!")
		
		console.log("方法一:pattern.test(o)");
		console.time("first");
		for (var i=0;i<10000;i++){
			ret = pattern.test(o);
		}
		console.timeEnd("first");
		console.log(ret);

		console.log("方法二:o instanceof Number");
		console.time("second");
		for (var i=0;i<10000;i++){
			ret = o instanceof Number;
		}
		console.timeEnd("second");
		console.log(ret);
		
		console.log("方法三:o.constructor == Number");
		console.time("thirth");
		for (var i=0;i<10000;i++){
			ret = o.constructor == Array;
		}
		console.timeEnd("thirth");
		console.log(ret);

		console.log("方法四:array[toStr.call(o)] == 'number'");
		console.time("forth");
		for (var i=0;i<10000;i++){
			ret = array[toStr.call(o)] == "number";
		}
		console.timeEnd("forth");
		console.log(ret);


<think> 根据用户当前查询,用户希望了解判断数组中不同数字种类的方法。结合之前的对话历史,用户可能正在学习编程或算法相关的内容。 我需要提供几种常见的方法来实现这个需求,并比较它们的优缺点。重点考虑时间复杂度和空间复杂度,因为这在处理大数据量时非常重要。 用户提到的"站内引用"在当前上下文中没有具体指向,因此我将主要专注于解决用户的核心问题。 准备提供以下方法: 1. 使用集合(Set)的特性 - 最简洁高效的方法 2. 使用字典(Dictionary)计数 - 可以同时获取每种数字的出现次数 3. 排序后遍历 - 不需要额外空间的方法 4. 使用数组标记 - 适用于数字范围已知的情况 对于每种方法,我会: - 说明基本思路 - 分析时间空间复杂度 - 给出简单代码示例(使用Python,因为之前示例用了Python) - 指出适用场景 最后会总结推荐方案,并根据不同场景给出建议。 考虑到用户之前的问题是关于快速排序的,可能会对算法效率感兴趣,因此需要详细解释复杂度分析。 还要注意回答要符合中文要求和格式规范: - 行内公式用$...$ - 独立公式用$$...$$并单独成段 - 代码块使用正确格式 - 生成相关问题 </think> ### 判断数组中不同数字种类的方法 要判断数组中不同数字的种类(即去重后的元素数量),以下是五种常用方法,根据不同场景选择: #### 1. **集合去重法**(推荐) 直接利用集合(Set)自动去重的特性: ```python def count_unique(arr): return len(set(arr)) ``` - **时间复杂度**:$O(n)$ - **空间复杂度**:$O(n)$ - **优点**:代码简洁,适合任意数据类型 - **缺点**:额外空间存储集合 #### 2. **字典计数法** 遍历数组并用字典记录元素出现次数: ```python def count_unique(arr): count_dict = {} for num in arr: count_dict[num] = count_dict.get(num, 0) + 1 return len(count_dict) ``` - **时间复杂度**:$O(n)$ - **空间复杂度**:$O(n)$ - **优点**:可同时获取每个元素的出现次数 - **缺点**:空间开销略大于集合法 #### 3. **排序遍历法**(节省空间) 先排序再统计相邻元素变化: ```python def count_unique(arr): if not arr: return 0 arr.sort() count = 1 for i in range(1, len(arr)): if arr[i] != arr[i-1]: count += 1 return count ``` - **时间复杂度**:$O(n \log n)$(主要来自排序) - **空间复杂度**:$O(1)$(原地排序时) - **适用场景**:内存有限且允许修改原数组 #### 4. **布尔数组标记法**(针对整数) 若元素范围已知(如 $[0, k]$),用布尔数组标记: ```python def count_unique(arr, max_val): seen = [False] * (max_val + 1) for num in arr: seen[num] = True return sum(seen) # True的数量即不同元素数 ``` - **时间复杂度**:$O(n)$ - **空间复杂度**:$O(k)$($k$为数值范围) - **适用场景**:元素为有限范围内的整数 #### 5. **NumPy库法**(Python科学计算) 使用`numpy.unique()`高效处理: ```python import numpy as np def count_unique(arr): return len(np.unique(arr)) ``` - **优点**:对大型数组性能极佳(底层C优化) - **缺点**:需安装NumPy库 --- ### 方法选择建议 | **场景** | **推荐方法** | **原因** | |-------------------------|--------------------|------------------------------| | 通用需求 | 集合去重法 | 代码简洁,效率高 | | 需统计元素频次 | 字典计数法 | 可扩展性强 | | 内存敏感 | 排序遍历法 | 空间复杂度最低 | | 整数且范围已知 | 布尔数组标记法 | 时间$O(n)$,无哈希冲突 | | 大型数值数组(如科学计算)| NumPy法 | 并行优化,性能碾压纯Python | > 📌 **关键公式** > 设数组长度为 $n$,不同元素数为 $k$: > - 哈希法(集合/字典)平均复杂度:$T(n) = O(n)$, $S(n) = O(\min(n, k))$ > - 排序法复杂度:$T(n) = O(n \log n)$, $S(n) = O(1)$ --- ### 相关问题 1. 如何找出数组中**频次最高**的数字? 2. 如果数组包含**浮点数**,去重时如何处理精度误差? 3. 在**分布式系统**中如何统计海量数据的不同元素数量? 4. 如何使用**位图(Bitmap)** 优化整数数组的去重操作? [^1]: 集合去重法的理论基础来自集合论中的元素互异性公理。 [^2]: 布尔数组标记法本质是桶排序(Bucket Sort)思想的变体应用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值