前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >温故而知新,ggplot2 饼图的几点笔记

温故而知新,ggplot2 饼图的几点笔记

作者头像
章鱼猫先生
发布于 2021-10-15 05:39:15
发布于 2021-10-15 05:39:15
1.4K00
代码可运行
举报
文章被收录于专栏:BioIT爱好者BioIT爱好者
运行总次数:0
代码可运行

其实 ggplot2 并没有类似于 geom_pie() 这样的函数实现饼图的绘制,它是由 geom_bar() 柱状图经过 coord_polar() 极坐标弯曲从而得到的。 对于为什么 ggplot2 中没有专门用于饼图绘制的函,有人说:“柱状图的高度,对应于饼图的弧度,饼图并不推荐,因为人类的眼睛比较弧度的能力比不上比较高度(柱状图)。” 关于饼状图被批评为可视化效果差,不推荐在 R 社区中使用的文章在网络也有不少,感兴趣的可以去搜一下。

不管怎么说,学习一下总不是坏事,趁着一些客户刚好对饼图有需求,重温一下。

极坐标系

极坐标应该是高中数学的知识,对我而言,基本都已经忘光了,结合网上的一些资料重温一下。

极坐标是指在平面内取一个定点 O,叫极点,引一条射线 Ox,叫做极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向)。对于平面内任何一点 M,用 ρ 表示线段 OM 的长度(有时也用 r 表示),θ 表示从 Ox 到 OM 的角度,ρ 叫做点 M 的极径,θ 叫做点 M 的极角,有序数对 (ρ, θ) 就叫点 M 的极坐标,这样建立的坐标系叫做极坐标系。通常情况下,M 的极径坐标单位为 1(长度单位),极角坐标单位为 rad(或 °)。

极坐标系中一个重要的特性是,平面直角坐标中的任意一点,可以在极坐标系中有无限种表达形式。通常来说,点(r, θ)可以任意表示为(r, θ ± n×360°)或 (−r, θ ± (2n + 1)180°),这里 n 是任意整数。如果某一点的 r 坐标为 0,那么无论 θ 取何值,该点的位置都落在了极点上。

笛卡尔坐标和极坐标之间的转换,请参考数学乐网站的《极坐标与笛卡尔坐标》一文,非常详细直观。

coord_polar

coord_polar()ggplot2 中的极坐标函数,它可以弯曲横纵坐标,使用这个函数做出蜘蛛图或饼图的效果。我在网络上查了一下,比较少看到关于 coord_polar() 原理的介绍,只是在 ggplot2 的 Tidyverse 上发现了几个例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
library(ggpubr)
library(ggplot2)

df <- data.frame(name = c("A", "B", "C"), value = c(10, 50, 30))
p <- ggplot(df, aes(x=name, y=value, fill=name)) + geom_bar(stat="identity", width=1, colour="black")
g <- ggplot(df, aes(x="", y=value, fill=name)) + geom_bar(stat="identity", width=1, colour="black")

用法

coord_polar() 主要有四个参数:thetastartdirectionclip

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
coord_polar(theta = "x", start = 0, direction = 1, clip = "on")
  • theta:variable to map angle to ( x or y ).
  • start:offset of starting point from 12 o'clock in radians.
  • direction:1, clockwise; -1, anticlockwise.
  • clip:Should drawing be clipped to the extent of the plot panel? A setting of "on" (the default) means yes, and a setting of "off" means no.

小知识:角度制 vs 弧度制 1度=π/180≈0.01745弧度,1弧度=180/π≈57.3度。 角的度量单位通常有两种,一种是角度制,另一种就是弧度制。角度制,就是用角的大小来度量角的大小的方法。在角度制中,我们把周角的 1/360 看作 1 度,那么,半周就是 180 度,一周就是 360 度。由于 1 度的大小不因为圆的大小而改变,所以角度大小是一个与圆的半径无关的量。 弧度制,顾名思义,就是用弧的长度来度量角的大小的方法。单位弧度定义为圆周上长度等于半径的圆弧与圆心构成的角。由于圆弧长短与圆半径之比,不因为圆的大小而改变,所以弧度数也是一个与圆的半径无关的量。角度以弧度给出时,通常不写弧度单位,有时记为 rad 或 R。

参数示例

结合一些示例,理解一下 coord_polar() 的几个参数。

  • theta="x"

x 轴极化,x 轴刻度值对应扇形弧度,y 轴刻度值对应圆环半径。p 中由于 x 是等长的,所以 p1 每一个弧度为 60 度;p2 的每一个弧度为 360 度。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p1 <- p + coord_polar(theta="x") + labs(title="theta=\"x\"")
g1 <- g + coord_polar(theta="x") + labs(title="theta=\"x\"")
ggarrange(p, g, p1, g1, ncol=2, nrow=2, labels=c("p", "g", "p1", "g1"))
  • theta="y"

y 轴极化,y 轴刻度值对应扇形弧度,x 轴长度对应扇形半径。对于并列柱状图 p,以最大的 y 值作为 360 度的弧度,剩下的按比例类推,由于 p 中 A、B、C 是等长的,所以在 p1 中它们的半径是 1:2:3。对于堆叠柱状图 g,把 y 值按照比例划分弧度,因此它们的弧度比等于各自的 y 值比例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p2 <- p + coord_polar(theta="y") + labs(title="theta=\"y\"")
g2 <- g + coord_polar(theta="y") + labs(title="theta=\"y\"")
ggarrange(p, g, p2, g2, ncol=2, nrow=2, labels=c("p", "g", "p2", "g2"))
  • start=pi/6, direction=1

起始位置为距离 12 点针方向 30 度,顺时针排列。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p3 <- p + coord_polar(theta="y", start=pi/6, direction=1) + labs(title="theta=\"x\",start=pi/6,direction=1")
g3 <- g + coord_polar(theta="y", start=pi/6, direction=1) + labs(title="theta=\"x\",start=pi/6,direction=1")
ggarrange(p, g, p3, g3, ncol=2, nrow=2, labels=c("p", "g", "p3", "g3"))
  • start=pi/6, direction=-1

起始位置为距离 12 点针方向 30 度,逆时针排序。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p4 <- p + coord_polar(theta="y", start=pi/6, direction=-1) + labs(title="theta=\"y\",start=pi/6,direction=-1")
g4 <- g + coord_polar(theta="y", start=pi/6, direction=-1) + labs(title="theta=\"y\",start=pi/6,direction=-1")
ggarrange(p, g, p4, g4, ncol=2, nrow=2, labels=c("p", "g", "p4", "g4"))
  • start=-pi/6, direction=1

起始位置为距离 12 点针方向负 30 度,顺时针排序。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p5 <- p + coord_polar(theta="y", start=-pi/6, direction=1) + labs(title="theta=\"y\",start=-pi/6,direction=1")
g5 <- g + coord_polar(theta="y", start=-pi/6, direction=1) + labs(title="theta=\"y\",start=-pi/6,direction=1")
ggarrange(p, g, p5, g5, ncol=2, nrow=2, labels=c("p", "g", "p5", "g5"))

Github 上有关于 coord-pola.r 的源码,整个代码只有 300 多行,有兴趣的同学可以去研究一下,上面的理解如有不对的地方还请帮忙指正。

饼图中添加文字的位置控制 - 借助公式

绘制饼图的过程中,利用 ggplot2geom_bar 结合 coord_polar 实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Load ggplot2
library(ggplot2)

# Create Data
data <- data.frame(group=LETTERS[1:5], value=c(13,7,9,21,2))

# Basic piechart
ggplot(data, aes(x="", y=value, fill=group)) +
  geom_bar(stat="identity", width=1) +
  coord_polar("y", start=0)

需要理解的点是饼图的排布是按照 aes(fill) 的因子顺序确定的。譬如数据如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> dat <- data.frame(type=LETTERS[1:5], Num=c(90, 34, 56, 99, 15))
> dat
  type Num
1    A  90
2    B  34
3    C  56
4    D  99
5    E  15

必须根据数据先确定 mappingaes(fill) 的因子顺序,譬如这里会按照 dat$type 填充,这种非有序因子会基于字母顺序来默认其填充顺序。

为了确定数据填充的先后,同时方便在不同区域上填写上对应数据的大小,所以会先去创建有序因子,从而使数据列 dat$Num 的自然顺序和因子的顺序在一定程度上一致(一致的同向对应或反向对应)。譬如如下使方向一致:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dat$type <- factor(dat$type,levels = dat$type,order=T)
dat$type

有序因子的结果则如下,和 dat$Num 的顺序能够一致上,不会出现对应错乱问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[1] A B C D E
Levels: A < B < C < D < E

画图:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p_pie <- ggplot(dat, aes(x="", y=dat[,2], fill=dat[,1]))+
  geom_bar(stat="identity", width=1)+
  coord_polar(theta="y", direction=1)+
  scale_fill_brewer(palette ="Set3", direction = 1)+
  labs(x="", y="", fill="Type")+
  ggtitle(label ="test", subtitle=NULL)
p_pie

结合下图结果可以看出坐标轴方向使顺时针,而颜色设置 scale_fill_brewer(palette ="Set3",direction = 1) 设定了第一个颜色填充到第一个因子对应的 “A” 上,这样就反映出在图片实际分布中数据和因子是反向对应的。虽然在 dat 数据框中设置是顺序一致方向相同的对应,但图片分布中会改变。

小知识:scale_fill_brewer scale_fill_brewer 是一个 ggplot2 和 RColorBrewer 关联的一个扩展调色板,其他可用于 scale_fill_brewer 调色板的颜色包括:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Diverging        BrBG, PiYG, PRGn, PuOr, RdBu, RdGy, RdYlBu, RdYlGn, Spectral
Qualitative     Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3
Sequential       Blues, BuGn, BuPu, GnBu, Greens, Greys, Oranges, OrRd, PuBu, 
                        PuBuGn, PuRd, Purples, RdPu, Reds, YlGn, YlGnBu, YlOrBr, YlOrRd

参考:https://ggplot2.tidyverse.org/reference/scale_brewer.html

结合图片中反向对应的关系,在 A 区块上中间位置填充上对应的文字 "Num:90",它的坐标因该是 sum(dat

sum(dat\$Num)-cumsum(dat$Num)+dat$Num/2,即:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> sum(dat$Num)-cumsum(dat$Num)+dat$Num/2
[1] 249.0 187.0 142.0  64.5   7.5

小知识:R 语言 cumsum 函数 cumsum 是 R 语言 base 包 cum 系列的一个函数,它的功能是计算向量的累积和并返回。

cum 系列还有另外三个函数:cumprodcummincummax ,它们的作用分别是计算向量的累积的乘积、极小值、极大值,并返回。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 对数值型向量求和
> cumsum(1:10)    
[1]  1  3  6 10 15 21 28 36 45 55

# 对数值型矩阵求和,结果返回仍是向量
> cumsum(matrix(1:12, nrow = 3))  
[1]  1  3  6 10 15 21 28 36 45 55 66 78

# 对数据框求和,返回结果仍然是数据框,cumsum 会对对每个变量进行求和处理
> cumsum(data.frame(a = 1:10, b = 21:30))  
   a   b
1   1  21
2   3  43
3   6  66
4  10  90
5  15 115
6  21 141
7  28 168
8  36 196
9  45 225
10 55 255

结合 geom_text(aes(x,y)) 的位置设置,保证中间文字填写不会出错:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p_pie=p_pie+
  geom_text(aes(x=1.2,y=sum(dat$Num)-cumsum(dat$Num)+dat$Num/2 ,label=as.character(dat[,2])),size=3)
p_pie

如果最初构建有序因子的方向和实际数据的方向反向对应呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dat$type=factor(dat$type,levels = rev(dat$type),order=T)
dat$type

p_pie=ggplot(dat,aes(x="",y=dat[,2],fill=dat[,1]))+
  geom_bar(stat="identity",width=1)+
  coord_polar(theta="y",direction=1)+
  scale_fill_brewer(palette ="Set3",direction = 1)+
  labs(x="",y="",fill="Type")+
  ggtitle(label ="test",subtitle=NULL)
p_pie

结合图片可以知道,第一个因子 "E" 对应了第一个颜色,不过从图片显示坐标中可以看到,"A" 在前,而 "A" 在原始数据 dat$Num 中对应的数据也在前 90,这样计算位置就会发生改变了,这时候 "A" 文字应该对应 90-90/2,文字 "B" 将对应 90+34-34/2,…,归纳为 cumsum(dat$Num)-dat$Num/2

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> cumsum(dat$Num)-dat$Num/2
[1]  45.0 107.0 152.0 229.5 286.5

而且图例也是反向的,需要结合 guides(fill=guide_legend(reverse=T)) ,并且希望第一个颜色对应最后一个因子 "A", scale_fill_brewer(palette ="Set3",direction = -1)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dat$type=factor(dat$type,levels = rev(dat$type),order=T)
dat$type

p_pie=ggplot(dat,aes(x="",y=dat[,2],fill=dat[,1]))+
  geom_bar(stat="identity",width=1)+
  coord_polar(theta="y",direction=1)+
  scale_fill_brewer(palette ="Set3",direction = -1)+
  labs(x="",y="",fill="Type")+
  ggtitle(label ="test",subtitle=NULL)+
  guides(fill=guide_legend(reverse = T))+
  geom_text(aes(x=1.2,y=cumsum(dat$Num)-dat$Num/2 ,label=as.character(dat[,2])),size=3)

p_pie

总结可知:ggplot2 在画饼图的过程中设定填充的因子方向总和图片坐标中的方向相反,不过因子的顺序和数据 dat$Num 的对应关系是正向对应或者反向对应,会影响相关区块的中心位置值计算的方式,从而影响 geom_text 中文字定位。

饼图中添加文字的位置控制(借助公式)部分的内容主要参考了 Daitoue 在 OmicsClass 的一篇文章(详见参考资料),OmicsClass 上还给出了不借助公式在饼图中添加文字的位置控制,感兴趣的同学也已点击文章左下角 "阅读原文" 进行阅读。

sessionInfo 信息

本次学习 R 和相关包版本信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> sessionInfo()
R version 3.6.2 (2019-12-12)
Platform: x86_64-conda_cos6-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS/LAPACK: /usr/local/software/miniconda3/lib/libopenblasp-r0.3.8.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
 [9] LC_ADDRESS=C               LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

other attached packages:
[1] ggplot2_3.2.1

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.3         viridisLite_0.3.0  digest_0.6.25      withr_2.1.2
 [5] crayon_1.3.4       dplyr_0.8.3        assertthat_0.2.1   grid_3.6.2
 [9] R6_2.4.0           gtable_0.3.0       magrittr_1.5       scales_1.0.0
[13] pillar_1.4.3       rlang_0.4.5        lazyeval_0.2.2     labeling_0.3
[17] RColorBrewer_1.1-2 glue_1.3.1         purrr_0.3.2        munsell_0.5.0
[21] compiler_3.6.2     pkgconfig_2.0.3    colorspace_1.4-1   tidyselect_0.2.5
[25] tibble_2.1.3
>

FAQ:如何实现 R 语言饼图标签的 overlap 问题?

文章的最后,提个问题:有没有通用的 R 包或者函数,可以得到下面效果的饼图?

参考资料

  • Daitoue,《饼图 pie - ggplot2》,OmicsClass
  • Daitoue,《饼图中添加文字的位置控制-ggplot2(非公式)》,OmicsClass
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BioIT爱好者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
C#创建安全的字典(Dictionary)存储结构
彭泽0902
2018/01/04
2.5K0
浅析C# Dictionary实现原理
本篇文章配图以及文字其实整理出来很久了,但是由于各种各样的原因推迟到现在才发出来,还有之前立Flag的《多线程编程》的笔记也都已经写好了,只是说还比较糙,需要找个时间整理一下才能和大家见面。
全球技术精选
2021/08/20
2370
Dictionary源码解析及实现原理(C#)
Dictionary 又称C#中的哈希表,是一个Collection(集合)类型,可以通过Key/Value(键值对)的形式来存放数据;该类最大的优点就是它查找元素的时间复杂度接近O(1),实际项目中常被用来做一些数据的本地缓存,提升整体效率。
用户11236293
2024/08/14
1450
.net源码分析 – Dictionary<TKey, TValue>
接上篇:.net源码分析 – List<T> Dictionary<TKey, TValue>源码地址:https://github.com/dotnet/corefx/blob/master/src
用户1147588
2018/01/04
1.8K0
.net源码分析 – Dictionary<TKey, TValue>
算法和数据结构: 十一 哈希表
在前面的系列文章中,依次介绍了基于无序列表的顺序查找,基于有序数组的二分查找,平衡查找树,以及红黑树,下图是他们在平均以及最差情况下的时间复杂度:
yaphetsfang
2020/07/30
1K0
算法和数据结构: 十一 哈希表
你真的了解字典吗(dictionary)?
半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.
码农阿宇
2019/02/13
6810
DotNet Dictionary 实现简介
本来笔者对DotNet的Hashtable及Dictionary认识一直集中在使用上,一个直接用object 一个可以用泛型,以前也只大概看过Hashtable的实现。最近查MSDN时发现有建议开发者使用Dictionary代替Hashtable的描述,出于好奇测试了Hashtable及Dictionary读写性能,发现无论读还是写Dictionary都大幅领先Hashtable,然后就花时间整理了Dictionary操作逻辑试图找到这种性能提升的原因(最后会发现实现上的差异带来的性能明显提升也算的上是理所当然)。下文实际是介绍的Dictionary的实现(调试中使用的源是corefx 3.1),其中穿插着对比了Hashtable的实现逻辑。
lulianqi
2022/03/11
3560
DotNet Dictionary 实现简介
.net源码分析 - ConcurrentDictionary<TKey, TValue>
List源码分析 Dictionary源码分析 ConcurrentDictionary源码分析 继上篇Dictionary源码分析,上篇讲过的在这里不会再重复 ConcurrentDiction
用户1147588
2018/01/04
1.3K0
ConsurrentDictionary并发字典知多少?
背景 在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理. 有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题. https://d
码农阿宇
2019/03/20
8930
ConsurrentDictionary并发字典知多少?
C#集合类型大揭秘
集合是.NET FCL(Framework Class Library)的重要组成部分,我们平常撸C#代码时免不了和集合打交道,FCL提供了丰富易用的集合类型,给我们撸码提供了极大的便利。正是因为这种与生俱来的便利性,使得我们对集合既熟悉又陌生。很多同学可能一直还是停留在使用的层面上,那么今天我们一起来深入学习一下C#语言中的各种集合。
撸码那些事
2018/06/15
1.2K0
C#集合类型大揭秘
我大意了,没有闪。
(1) 栗子1重新new赋值难道不是修改了原字典对象newDict吗?foreach字典为什么不报InvalidOperation异常?
有态度的马甲
2023/09/05
2520
我大意了,没有闪。
【算法与数据结构】--高级算法和数据结构--哈希表和集合
哈希表(Hash Table)是一种常用的数据结构,其核心原理是将数据存储在数组中,并使用哈希函数来映射数据的键(Key)到数组中的特定位置,这个位置通常被称为“哈希桶”或“槽位”。哈希表允许快速的数据查找、插入和删除操作,通常在平均情况下,这些操作的时间复杂度为O(1)。以下是哈希表的基本原理:
喵叔
2023/10/17
5380
C# Dictionary 字典
说明 必须包含名空间System.Collection.Generic Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值) 键必须是唯一的,而值不需要唯一的 键和值都可以是任何类型(比如:string, int, 自定义类型,等等) 通过一个键读取一个值的时间是接近O(1) 键值对之间的偏序可以不定义
zls365
2021/03/16
1.2K0
.NET中的泛型集合
近对集合相关的命名空间比较感兴趣,以前也就用下List, Dictionary<Tkey, TValue>之类,总之,比较小白。点开N多博客,MSDN,StackOverflow,没找到令我完全满意的答案,本打算自己总结下写出来,工作量好大的感觉……直到昨晚随意翻到看了一些又放下的《深入理解C#》-附录B部分,高兴地简直要叫出来——“这总结真是太绝了,好书不愧是好书”。真是“踏破铁鞋无觅处,得来全不费工夫”,最好的资源就在眼下,而自己居然浑然不知。或许只有深入技术细节的时候,才能认识到经典为什么经典吧!言归正传,本博客主要是对《深入理解C#》-附录B的摘录,并加了些标注。
郑子铭
2023/08/29
2850
.NET中的泛型集合
数据结构基础温故-6.查找(下):哈希表
哈希(散列)技术既是一种存储方法,也是一种查找方法。然而它与线性表、树、图等结构不同的是,前面几种结构,数据元素之间都存在某种逻辑关系,可以用连线图示表示出来,而哈希技术的记录之间不存在什么逻辑关系,它只与关键字有关联。因此,哈希主要是面向查找的存储结构。哈希技术最适合的求解问题是查找与给定值相等的记录。
Edison Zhou
2018/08/20
6270
数据结构基础温故-6.查找(下):哈希表
C#中HashTable、Dictionary、ConcurrentDictionary区别
HashTable表示键/值对的集合。在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key-value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key-value键值对均为object类型,所以Hashtable可以支持任何类型的keyvalue键值对,任何非 null 对象都可以用作键或值。
用户9127601
2021/11/01
8630
.NET 排序 Array.Sort<T> 实现分析
System.Array.Sort<T> 是.NET内置的排序方法, 灵活且高效, 大家都学过一些排序算法,比如冒泡排序,插入排序,堆排序等,不过你知道这个方法背后使用了什么排序算法吗? 先说结果,
全球技术精选
2021/10/09
6590
.NET 排序 Array.Sort<T> 实现分析
CSharp中字典(Dictionary)的使用
Dictionary<TKey, TValue> 是泛型类型,其中 TKey 表示键的类型,TValue 表示值的类型。
码客说
2024/05/30
4090
C#集合类型大揭秘
集合是.NET FCL(Framework Class Library)的重要组成部分,我们平常撸C#代码时免不了和集合打交道,FCL提供了丰富易用的集合类型,给我们撸码提供了极大的便利。正是因为这种
撸码那些事
2018/06/21
1.6K0
面试时被问到Flutter/Dart的HashMap怎么办?
相信不少同学在面试的时候有被问到关于HashMap的问题,特别是Java/Android程序员,HashMap几乎是必然会被提及的。因为这里面可以挖掘的点实在是太多了。关于Java的HashMap面经在网上可以说是随处可见了。自然而然,随着Flutter的火爆,后面大家也可能在面试中被问到关于Flutter/Dart的HashMap相关问题。与其到时候一问三不知,不如现在就来了解一下Flutter/Dart的HashMap吧。
HowHardCanItBe
2021/05/21
1.2K0
相关推荐
C#创建安全的字典(Dictionary)存储结构
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档