rust的排序

Vec 中的 Methods from Deref<Target = [T]>

示例

fn main() {let mut strings = vec!["banana", "", "ban", "", "apple", "alpha", "cherry", "date"];strings.sort_by(|a, b| {if a.len() == 0 {return std::cmp::Ordering::Less;}if b.len() == 0 {return std::cmp::Ordering::Greater;}// pub fn chars(&self) -> Chars<'_> 返回一个基于字符数组之上的迭代器// fn next(&mut self) -> Option<char> 通过迭代器遍字符let cmp = a.chars().next().unwrap().cmp(&b.chars().next().unwrap());if cmp == std::cmp::Ordering::Equal {a.len().cmp(&b.len())} else {cmp}});println!("{:?}", strings); // 输出:["alpha", "apple", "banana", "cherry", "date"]
}

打印结果:[“”, “”, “apple”, “alpha”, “ban”, “banana”, “cherry”, “date”]

Slice

sort

pub fn sort(&mut self)
whereT: Ord,

这种排序是稳定的(即,不会对相等的元素重新排序)并且最坏情况为 O(n * log(n))。
如果适用,首选不稳定排序(unstable sorting),因为它通常比稳定排序(stable sorting)更快,并且不分配辅助内存。

当前的算法是受 timsort 启发的自适应迭代合并排序。它被设计为在切片几乎是排好序或由两个或多个依次连接的排序序列组成的情况下非常快( the slice is nearly sorted, or consists of two or more sorted sequences concatenated one after another.)。
此外,它分配的临时存储空间是 self 大小的一半,但对于短切片,则使用非分配插入排序(a non-allocating insertion sort)。

let mut v = [-5, 4, 1, -3, 2];v.sort();
assert!(v == [-5, -3, 1, 2, 4]);

sort_by

pub fn sort_by<F>(&mut self, compare: F)
whereF: FnMut(&T, &T) -> Ordering,

使用比较器函数(a comparator function)对切片进行排序。
这种排序是稳定的(即,不会对相等的元素重新排序)并且最坏情况为 O(n * log(n))。
比较器函数必须定义切片中元素的total ordering(define a total ordering for the elements in the slice)。如果排序不是全部,则元素的顺序未指定。total ordering的含义(对于所有 a、b 和 c):

  • 完全和反对称total and antisymmetric:a < b、a == b 或 a > b 中的一个为真,并且
  • 传递transitive,a < b 和 b < c 意味着 a < c(同样适用于 == 和 >)

例如,虽然 f64 没有实现 Ord,因为 NaN != NaN,但当我们知道切片不包含 NaN 时,可以使用partial_cmp 作为排序函数。

let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0];
floats.sort_by(|a, b| a.partial_cmp(b).unwrap());
assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]);
// Panic
let mut floats = [5f64, std::f64::NAN, 4.0, 1.0, 3.0, 2.0];
floats.sort_by(|a, b| a.partial_cmp(b).unwrap());
println!("floats is {:?}", floats);

说明同上

let mut v = [5, 4, 1, 3, 2];
v.sort_by(|a, b| a.cmp(b));
assert!(v == [1, 2, 3, 4, 5]);// reverse sorting
v.sort_by(|a, b| b.cmp(a));
assert!(v == [5, 4, 3, 2, 1]);

sort_by_key

pub fn sort_by_key<K, F>(&mut self, f: F)
whereF: FnMut(&T) -> K,K: Ord,

使用键提取函数对切片进行排序。
这种排序是稳定的(即,不会对相等的元素重新排序),最坏情况为 O(m * n * log(n)),其中关键函数为 O(m)。
对于昂贵的键函数(例如,不是简单属性访问或基本操作的函数),sort_by_cached_key 可能会快得多,因为它不会重新计算元素键。

let mut v = [-5i32, 4, 1, -3, 2];v.sort_by_key(|k| k.abs());
assert!(v == [1, 2, -3, 4, -5]);

可以理解为排序不是按照v中的元素来排序,而是把元素处理后再排序,最后排序完后,按照key的结果有序

sort_by_cached_key

pub fn sort_by_cached_key<K, F>(&mut self, f: F)
whereF: FnMut(&T) -> K,K: Ord,

使用键提取函数对切片进行排序。
在排序过程中,每个元素最多调用一次 key 函数,通过使用临时存储来记住 key 评估的结果。关键函数的调用顺序未指定,并且在标准库的未来版本中可能会发生变化。
这种排序是稳定的(即,不会对相等的元素重新排序),最坏情况为 O(m * n + n * log(n)),其中关键函数为 O(m)。
对于简单的键函数(例如,属性访问或基本操作的函数),sort_by_key 可能会更快。

当前的算法基于 Orson Peters 提出的模式击败快速排序( pattern-defeating quicksort),它将随机快速排序的快速平均情况与堆排序的快速最坏情况相结合,同时在具有某些模式的切片上实现线性时间。它使用一些随机化来避免退化情况,但使用固定种子始终提供确定性行为。
在最坏的情况下,算法会在 Vec<(K, usize)> 切片长度中分配临时存储。

let mut v = [-5i32, 4, 32, -3, 2];v.sort_by_cached_key(|k| k.to_string());
assert!(v == [-3, -5, 2, 32, 4]);

什么是Methods from Deref<Target = [T]>

Deref<Target = [T]> 是一个trait,在Rust中被用于智能指针或其他类型上,以提供对目标类型 [T] 中方法的调用。

根据 Deref trait 文档,Deref trait 定义了一个方法 deref,该方法用于将类型转换为其目标类型。对于 Deref<Target = [T]>,目标类型为 [T],意味着它将实现 deref 方法,用于将类型转换为 [T]。

这允许在实现了 Deref<Target = [T]> 的类型上,通过 * 运算符或使用智能指针解引用操作符 &,来访问目标类型中的方法。

示例

use std::ops::Deref;fn main() {let vec = vec![1, 2, 3];// 将 Vec<i32> 转换为 &[i32]let slice: &[i32] = vec.deref();// 通过解引用操作符调用 &[i32] 的方法// slice 方法:// pub fn iter(&self) -> Iter<'_, T>// // Iter结构体如下所示:// pub struct Iter<'a, T>// where//     T: 'a,// { /* private fields */ }let sum: i32 = slice.iter().sum();println!("Sum: {}", sum); // 输出:Sum: 6
}

使用 deref 方法将其转换为 &[i32] 类型的切片。
接下来,使用解引用操作符 *(deref 方法已自动完成解引用)来调用切片的 iter 方法,然后通过 sum 方法计算切片中元素的总和。

这只是 Deref<Target = [T]> trait 的用法之一,它为具备目标类型为 &[T](切片)的智能指针或类型提供了方便的调用方式。

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

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

相关文章

CUDA学习笔记(七)Kernel性能调节

本篇博文转载于https://www.cnblogs.com/1024incn/tag/CUDA/&#xff0c;仅用于学习。 Exposing Parallelism 这部分主要介绍并行分析&#xff0c;涉及掌握nvprof的几个metric参数&#xff0c;具体的这些调节为什么会影响性能会在后续博文解释。 代码准备 下面是我们的kernel…

类和对象介绍

一、类 1.类的声明 class Box{//类名private://私有成员double width,length,height;//长&#xff0c;宽&#xff0c;高 public://公有成员void init(double l,double w,double h){//初始化 lengthl;widthw;heighth;}double S(){//求表面积 return (height*lengthheight*width…

【Lua语法】字符串

Lua语言中的字符串是不可变值。不能像在C语言中那样直接改变某个字符串中的某个字符&#xff0c;但是可以通过创建一个新字符串的方式来达到修改的目的 print(add2(1 , 2 ,15,3))a "no one"b string.gsub(a , "no" , "on1111")print(a) print…

【Python】AttributeError: module lib has no attribute X509_V_FLAG_CB_ISSUER_CHECK

问题&#xff1a; 运行脚本报错&#xff1a;module lib has no attribute X509_V_FLAG_CB_ISSUER_CHECK 原因&#xff1a; pyOpenSSL版本与python版本不匹配 解决方案&#xff1a; window系统 重新安装pyOpenSSL 1、卸载当前版本pyOpenSSL pip uninstall pyOpenSSL2、重新…

flink问题 集合

1.flink 乱码 在配置文件flink-conf.yaml增加配置项&#xff1a;env.java.opts: -Dfile.encodingUTF-8

神经网络的不同类型的层

神经网络可以包含多个不同类型的层&#xff0c;每种层都具有不同的特点和应用场景。以下是常见的神经网络层的分类及其详细特点和应用场景&#xff1a; 1. 输入层&#xff08;Input Layer&#xff09;&#xff1a; 特点&#xff1a;输入层通常不包含任何权重或激活函数&#…

第87步 时间序列建模实战:LSTM回归建模

基于WIN10的64位系统演示 一、写在前面 这一期&#xff0c;我们介绍大名鼎鼎的LSTM回归。 同样&#xff0c;这里使用这个数据&#xff1a; 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Renal…

Compose Desktop 使用中的几个问题(分平台加载资源、编写Gradle 任务下载平台资源、桌面特有组件、鼠标键盘事件)

前言 在我之前的文章 Compose For Desktop 实践&#xff1a;使用 Compose-jb 做一个时间水印助手 中&#xff0c;我们使用 Compose For Desktop 写了一个用于读取照片 EXIF 中的拍摄日期参数并以文字水印的方式添加到照片上的桌面程序。 但是事实上&#xff0c;这个程序的名字…

从入门到进阶 之 ElasticSearch SpringData 继承篇

&#x1f339; 以上分享 从入门到进阶 之 ElasticSearch SpringData 继承篇&#xff0c;如有问题请指教写。&#x1f339;&#x1f339; 如你对技术也感兴趣&#xff0c;欢迎交流。&#x1f339;&#x1f339;&#x1f339; 如有需要&#xff0c;请&#x1f44d;点赞&#x1f…

PHP数据加密传输和存储问题

PHP数据加密的类型 md5()&#xff0c;sha1()&#xff0c;crypt() 双md5加密加盐

AAPCS:最新的ARM子程序调用规则

AAPCS是arm公司发布的ARM架构应用程序二进制&#xff08;ABI&#xff09;程序调用接口&#xff0c;该文档由多个版本&#xff0c;博主第一次ARM程序调用规则是在《ARM体系与结构编程》&#xff0c;但书中描述的是ATPCS&#xff0c;AAPCS是ATPCS的升级版。后面去ARM官网看到了AA…

自然语言处理基础——词表示

词表示 把自然语言中最基本的语言单元——词转换为机器能够理解的 词表示能完成以下两个能力 词相似度计算 词与词之间语义的关系 近义词&上位词 使用近义词或上位词表示的问题 遗漏差异 遗漏新的释义 带有主观性 数据吸收 需要大量人工构建 One-Hot Representation …

Kafka学习(最新版3.6.0)

文章目录 一、初识MQ1.1 什么是MQ1.2 同步和异步通讯1.1.1 同步通讯1.1.2 异步通讯 1.3 技术对比1.4 MQ的两种模式 二、初识Kafka2.1 Kafka的使用场景2.2 Kafka基本概念2.3 Topic与Partition 三、Kafka基本使用3.1 部署前的准备3.2 启动kafka服务器3.3 Kafka核心概念之Topic3.4…

【每日一题Day354】LC2316统计无向图中无法互相到达点对数 | 并查集

统计无向图中无法互相到达点对数【LC2316】 给你一个整数 n &#xff0c;表示一张 无向图 中有 n 个节点&#xff0c;编号为 0 到 n - 1 。同时给你一个二维整数数组 edges &#xff0c;其中 edges[i] [ai, bi] 表示节点 ai 和 bi 之间有一条 无向 边。 请你返回 无法互相到达…

059:mapboxGL监听键盘事件,通过eastTo控制左右旋转

第059个 点击查看专栏目录 本示例是介绍演示如何在vue+mapbox中监听键盘事件,通过eastTo控制左右旋转。 本例通过easeTo方法来加减一定数值的bearing角度,通过.addEventListener的方法来监听键盘的按键动作。这里一定要设置interactive: false, 否则展现不出来旋转效果。 直…

机械设备经营小程序商城的作用是什么

由于机械设备厂商品牌需要各地招商代理&#xff0c;因此在管理方面也需要工具进行高效管理。如今各个行业都在开展数字化转型解决行业所遇难题或通过线上销售解决传统三公里难题及品牌扩张难题、用户消费渠道少等难题&#xff0c;构建会员体系精细化管理&#xff0c;同时还需要…

MySQL 主从复制原理

文章目录 1.主从复制方式1.1 异步复制1.2 半同步复制1.3 全同步复制 2.主从复制原理3.主从复制时推还是拉&#xff1f;参考文献 主从复制是 MySQL 高可用&#xff08;备份&#xff09;和高性能&#xff08;读写分离&#xff09;的基础&#xff0c;有了这个基础&#xff0c;MySQ…

qt 开发api文档地址

直达Qt5开发api文档&#xff0c;doc.qt.io/qt-5/classes.html 打开www.qt.io后右上角的Developers点进去&#xff0c;然后Qt Documentation下面的View All C Classes 点进去就是api了。

代码随想录算法训练营Day60|单调栈01

代码随想录算法训练营Day60|单调栈01 文章目录 代码随想录算法训练营Day60|单调栈01一、739. 每日温度二、496.下一个更大元素 I 一、739. 每日温度 class Solution {public int[] dailyTemperatures(int[] temperatures) {//单调栈int lenstemperatures.length;int result[]n…

Java设计模式之状态模式

状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在内部状态改变时改变其行为。该模式将对象的行为封装在不同的状态类中&#xff0c;使得对象在不同的状态下可以有不同的行为&#xff0c;从而实现了状态的切换和行为的变化。 在状态…