文章目录

内排序:排序数据在内存中进行排序过程。
外排序:由于数据量太大,无法一次性将所有数据放入内存中,在排序过程中需要对磁盘等外部储存器进行边访问边排序。
| 方法 | 时间复杂度-平均 | 时间复杂度-最坏 | 时间复杂度-最好 | 空间复杂度 | 稳定性 | 适用情况 |
|---|---|---|---|---|---|---|
| 冒泡 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 稳定 | 记录较少或元素基本有序时 |
| 选择 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 | 记录较少时 |
| 快速 | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n 2 ) O(n^2) O(n2) | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | 不稳定 | 记录较多且元素无序时 |
| 插入 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 稳定 | 记录较少或元素基本有序时 |
| 希尔 | O ( n 1.3 ) O(n^{1.3}) O(n1.3) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 不稳定 | 记录较多时 |
| 堆 | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( 1 ) O(1) O(1) | 不稳定 | 记录较多时 |
| 归并 | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) | O ( n ) O(n) O(n) | 稳定 | 记录较多时 |
| 计数 | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | 稳定 | 记录间隔小,重复率高,且较多时 |
| 桶 | O ( n + k ) O(n+k) O(n+k) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n + k ) O(n+k) O(n+k) | 稳定 | 记录间隔小,且较多时 |
| 基数 | O ( n × k ) O(n \times k) O(n×k) | O ( n × k ) O(n \times k) O(n×k) | O ( n × k ) O(n \times k) O(n×k) | O ( n + k ) O(n+k) O(n+k) | 稳定 | 记录较多且元素较小时 |

冒泡排序是最常见的一种排序方式,冒泡的过程就是:
let bubbleSort = (arr) => {
for (let i = arr.length - 1, tmp; i > 0; i--) {
for (let j = 0; j < i; j++) {
tmp = arr[j]
if (tmp > arr[j + 1]) {
arr[j] = arr[j + 1]
arr[j + 1] = tmp
}
}
}
return arr
}
可以使用临时变量,熟练了之后也可以使用解构的方式简化操作
let bubbleSort = (arr) => {
for (let i = arr.length - 1; i > 0; i--) {
for (let j = 0; j < i; j++) {
[arr[j], arr[j + 1]] = arr[j] < arr[j + 1] ? [arr[j + 1], arr[j]] : [arr[j], arr[j + 1]]
}
}
return arr
}
也叫做定向冒泡排序,它的改进在于同时的冒泡两边,从低到高,然后从高到低,相当于同时把最小的数也冒泡到最前面,这个方法比冒泡更加高效
let cocktailSort= (arr) => {
let L = 0
let R = arr.length-1
while(L < R) {
for (let i = L; i < R; i++) {
[arr[i], arr[i + 1]] = arr[i] > arr[i + 1] ? [arr[i + 1], arr[i]] : [arr[i], arr[i + 1]]
}
R--
for (let i = R; i > L; i--) {
[arr[i], arr[i - 1]] = arr[i] < arr[i - 1] ? [arr[i - 1], arr[i]] : [arr[i], arr[i - 1]]
}
L++
}
return arr
}
let selectionSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
min = arr[i]
for (let j = i + 1; j < len; j++) {
if (arr[j] < min) {
let c = min
min = arr[j]
arr[j] = c
}
}
arr[i] = min
}
return arr
}
感觉以上课程提供的选择排序源码有些问题,并不是纯粹的选择排序,因为它里面的min存的是元素内容而不是元素下标,并且发现目标后直接交换内容而不是暂存,这两个操作也是识别选择排序的标志性操作
修改后如下(交换过程也使用了解构赋值):
let selectionSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
min = i
for (let j = i + 1; j < len; j++) {
min = arr[j] < arr[min] ? j : min
}
[arr[i], arr[min]] = [arr[min], arr[i]]
}
return arr
}
选取第一个数为基准
将比基准小的数交换到左面,比基准大的数交换到右面
对左右区间重复第二步,直到各区间只有一个数

快速排序使用的空间是O(1)的,也就是个常数级;而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据:
let quickSort = (arr) => {
// 如果数组<=1,则直接返回
if (arr.length < 2) return arr
// 找基准,并把基准从原数组删除
let pivot = arr.shift()
// 定义左右区间
let left = []
let right = []
// 比基准小的放在left,比基准大的放在right
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
// 递归
return quickSort(left).concat([pivot], quickSort(right))
}
将该数列的第一元素视为有序数列,后面都视为无序数列
将无序数列中的元素依次对比有序数列的元素并插入到有序数列的对应位置
插入排序算法,只需要两个变量暂存当前数,以及下标,与 n n n的大小无关,所以空间复杂度为: O ( 1 ) O(1) O(1)
let insertionSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
// i:未排序部分的当前位置
let value = arr[i] // 准备插入的值(新牌)
// j:已排序部分的当前位置
let j = i - 1 // 已经排好序最后一个元素位置
// 如果当已排序部分的当前元素大于value
while (j >= 0 && arr[j] > value) {
arr[j + 1] = arr[j] // 将当前元素向后移一位,再将前一位与value比较
j--
}
// 否则直接插入,新牌落位
arr[j + 1] = value
}
return arr
}
二分插入排序与直接插排最大的区别在于查找插入位置时使用的是二分查找的方式,,有效提高排序效率(线性查找 => 折半查找),步骤如下:
let insertionSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
let low = 0
let high = i - 1 // 已经排序的最大元素的位置
let value = arr[i] // 将要插入的值
while (low < high) { // 在已排序的元素中二分查找第一个比它大的值
let mid = Math.floor((low + high) / 2) // 二分查找的中间值
if (value < arr[mid]) { // 当前值比中间值小 则在左边的子数组中继续寻找
high = mid - 1
} else {
low = mid + 1 // 当前值比中间值大 在右边的子数组继续寻找
}
// console.log('low', low, 'high', high) // 测试查找位置过程
}
for (let j = i - 1; j >= low; j--) {
arr[j + 1] = arr[j]
}
arr[low] = value
// console.log('low', low) // 测试单次排序插入位置
// console.log('high', high)
// console.log(arr) // 测试单次排序结果
}
return arr
}
希尔排序的实质是分组插入排序,该方法又称缩小增量排序,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
算法思想:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列合并为一时再对全体记录进行一次直接插入排序
相比插入排序优点:分组后的排序是组内交换,可以将整个排序过程中平均交换次数压缩(插入排序插入一个特别小的元素时,需要其余元素全部移动,排序效率特别低。)
希尔排序,只需要一个变量用于两数交换,与n的大小无关,所以空间复杂度为: O ( 1 ) O(1) O(1)
let shallSort = (arr) => {
for (let increment = arr.length, temp; increment > 1;) {
// 设置增量
increment = Math.floor(increment / 3) + 1
for (let i = increment; i < arr.length; i++) {
if (arr[i] < arr[i - increment]) {
temp = arr[i]
while (i >= increment && temp < arr[i - increment]) {
arr[i] = arr[i - increment]
i -= increment
}
arr[i] = temp
}
}
}
return arr
}
看到其他小伙伴这样写希尔排序,这不是吧。。
let shallSort = (arr) => {
let gap = 1
// 动态定义间隔序列
while (gap < arr.length / 3) {
gap = gap * 3 + 1
}
// 上面是设置动态增量算法
// 下面是其实是组内冒泡排序
while (gap >= 1) {
console.log(gap)
for (let i = 0; i < arr.length; i++) {
for (let j = i; j >= gap && arr[j] < arr[j - gap]; j -= gap) {
[arr[j - gap], arr[j]] = [arr[j], arr[j - gap]]
}
}
gap = (gap - 1) / 3
}
return arr
}
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
算法思想:将待排序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆),此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
堆排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为 O ( n ) O(n) O(n),在交换并重建堆的过程中,需交换 n − 1 n-1 n−1次,而重建堆的过程中,根据完全二叉树的性质, [ l o g 2 ( n − 1 ) , l o g 2 ( n − 2 ) . . . 1 ] [log_2(n-1),log_2(n-2)...1] [log2(n−1),log2(n−2)...1]逐步递减,近似为 n l o g 2 n nlog_2n nlog2n。所以堆排序时间复杂度最好和最坏情况下都是 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)。
堆排序不要任何辅助数组,只需要一个辅助变量,所占空间是常数与n无关,所以空间复杂度为 O ( 1 ) O(1) O(1)
let len // 因为声明的多个函数都需要数列长度,所以把len设置成为全局变量
/**
* 堆调整
* @param arr 需要调整的数组
* @param i 预调整元素下标
*/
let adjustHeap = (arr, i) => {
let left = 2 * i + 1
let right = 2 * i + 2
// arr[i]预调整元素
let max = i
// 下面两步找到左右子树中最大的一个的下标
if (left < len && arr[left] > arr[max]) {
max = left
}
if (right < len && arr[right] > arr[max]) {
max = right
}
// 将左右子树的最大值赋给父节点(里面执行说明min有变动)
if (max !== i) {
[arr[max], arr[i]] = [arr[i], arr[max]]
adjustHeap(arr, max) // 这步递归为确保本枝杈下端的最大值提到当前父端(arr[max])
// console.log('调整结果', arr) // 调试代码时,这里打一个输出,每次排序结果都抓的死死的
}
}
let heapSort = arr => {
len = arr.length
// 构建大顶堆
for (let i = Math.floor(len / 2); i >= 0; i--) {
adjustHeap(arr, i)
}
// console.log('大顶堆:', arr) // 调试时这里也是一个关键点
// 堆排序
for (let i = len - 1; i > 0; i--) {
// 将堆顶(树根)置换到相应位置
[arr[0], arr[i]] = [arr[i], arr[0]]
len-- // 此时len表示的是未排序的arr长度
adjustHeap(arr, 0)
}
return arr
}
console.log(heapSort([6, 5, 3, 4, 2, 1]))
代码调试过程:
/**
* 排序前塑造大顶堆的两个目的:
* 1.使数列相对有序(与想要结果相反的顺序)
* 2.将最大值放到堆顶,方便排序时调换
* ----------------------------------------
* 起始数列:[3, 5, 1, 4, 2, 6]
* 排序过程中数列发生的置换过程如下(不包含组建大顶堆过程):
* 大顶堆:[6, 5, 3, 4, 2, 1]
* [1, 5, 3, 4, 2, 6] // 第〇次排序结果
* [5, 1, 3, 4, 2, 6]
* [5, 4, 3, 1, 2, 6]
* [2, 4, 3, 1, 5, 6] // 第一次排序结果
* // 在接下来的过程中即使 arr[left] > arr[max] 或 arr[right] > arr[max],都不会发生置换,
* // 因为len--这一步使得left < len 或 right < len 不满足
* [4, 2, 3, 1, 5, 6]
* [1, 2, 3, 4, 5, 6] // 第二次排序结果,这里其实已经排好了,但是排序过程还是会继续下去。。。
* [3, 2, 1, 4, 5, 6]
* [1, 2, 3, 4, 5, 6] // 第三次排序结果
* [2, 1, 3, 4, 5, 6]
* [1, 2, 3, 4, 5, 6] // 第四次排序结果
* [1, 2, 3, 4, 5, 6] // 第五次排序结果,虽然只剩一位,但还是要走排序过程,排除“后面”还有更大的(这时len已经是1了。。。没有后面了)
* 调试过程中断点位置如下:
* - max = left
* - max = right
* - len--
* 找好断点,搭配 Watch 监听器和 console.log(代码中已标出) ,过一遍排序流程,立刻感觉这是人能想出来的方法???
*/
归并排序就是递归地将原始数列递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序

/**
* 归并排序核心方法
* @param left
* @param right
* @returns {[]}
*/
let merge = (left, right) => {
let result = []
// 这里进行首次排序
while (left.length > 0 && right.length > 0) {
if (left[0] <= right[0]) {
result.push(left.shift())
} else {
result.push(right.shift())
}
}
console.log('result', result)
// 当左右数组长度不等.将比较完后剩下的元素链接起来即可
return result.concat(left).concat(right)
}
let mergeSort = arr => {
let len = arr.length
if (len < 2) {
// 递归分隔结束处,也是归并排序开始处
return arr
}
let middle = Math.ceil(len / 2)
let left = arr.slice(0, middle)
let right = arr.slice(middle)
console.log('left', left, 'right', right)
// 这里是递归和归并的核心,先递归分隔,后归并排序
return merge(mergeSort(left), mergeSort(right))
}
测试断点适合打在四个result.push(归并排序过程)和return arr(递归分隔过程)处,调试过程如下:

递归算法的时间复杂度公式:
T
[
n
]
=
a
T
[
n
/
b
]
+
f
(
n
)
T[n] = aT[n/b] + f(n)
T[n]=aT[n/b]+f(n)

无论原始数组是否是有序的,都要递归分隔并向上归并排序,所以时间复杂度始终是
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)
每次两个数组进行归并排序的时候,都会利用一个长度为n的数组作为辅助数组用于保存合并序列,所以空间复杂度为
O
(
n
)
O(n)
O(n)
计数排序基于一个假设,假设待排序数列的所有数均为整数,且出现在(0,max)的区间之内。如果 max(待排数组的最大值) 过大则会引起较大的空间复杂度,一般是用来排序 0 到 100 之间的数字的最好的算法,但是它只适用于大于0的正整数排序。
计数排序不是比较排序,对于较小的正整数序列排序的速度快于任何比较排序算法。
算法思想:
计数排序是一个稳定的排序算法。当输入的元素是 n 个 0到 k 之间的整数时,时间复杂度是O(n+k),空间复杂度也是O(n+k),其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法
let countingSort = (arr) => {
let maxValue = arr[0] // 数组中最大值
let minValue = arr[0] // 数组中最小值
// 求数组中最大值
arr.forEach(item => { maxValue = maxValue > item ? maxValue : item })
// 求数组中最小值
arr.forEach(item => { minValue = minValue < item ? minValue : item })
let sortedIndex = 0 // 遍历排序时的数组下标
let bucket = [] // 临时用来标注的’桶‘(元素存在标注1,否则0)
// 统计每种数的个数
for (let i = 0; i < arr.length; i++) {
if (!bucket[arr[i]]) bucket[arr[i]] = 0
bucket[arr[i]]++
}
// console.log(bucket) // 统计(标注)完成,有必要查看一下
// 从最小下标开始到最大下标,遍历赋值完成排序
for (let j = minValue; j <= maxValue; j++) {
while (bucket[j] > 0) {
arr[sortedIndex] = j
sortedIndex++
bucket[j]-- // 1 => 0
}
}
return arr
}
将值为i的元素放入i号桶,最后依次把桶里的元素倒出来。
算法思想:
设置一个定量的数组当作空桶子。
寻访序列,并且把项目一个一个放到对应的桶子去。
对每个不是空的桶子进行排序。
从不是空的桶子里把项目再放回原来的序列中。
一个桶使用计数排序。。。(网上好多都是这种。。。)
let bucketSort = (arr) => {
// 声明一个空桶, 将数据压入桶中
const bucket = []
// 统计每种数的个数
arr.forEach(item => {
if (bucket[item] !== undefined) {
bucket[item]++
} else {
bucket[item] = 1
}
})
arr.length = 0
console.log(bucket) // 统计(标注)完成,有必要查看一下
bucket.forEach((item, index) => {
if (item) {
for (let i = 0; i < item; i++) {
arr.push(index)
}
}
})
return arr
}
对于桶排序来说,我认为最重要的一点是桶的数量和容量,其实,桶的容量也是由桶的数量来决定的,而同的数量取决于数列的最大元素,在适当范围内,桶的数量多些,排序会更加高效。
真正的桶排序:
let insertionSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
// i:未排序部分的当前位置
let value = arr[i] // 准备插入的值(新牌)
// j:已排序部分的当前位置
let j = i - 1 // 已经排好序最后一个元素位置
// 如果当已排序部分的当前元素大于value
while (j >= 0 && arr[j] > value) {
arr[j + 1] = arr[j] // 将当前元素向后移一位,再将前一位与value比较
j--
}
// 否则直接插入,新牌落位
arr[j + 1] = value
}
return arr
}
let bucketSort = (arr) => {
let maxValue = arr[0] // 数组中最大值
// 求数组中最大值
arr.forEach(item => { maxValue = maxValue > item ? maxValue : item })
// 创建桶数组(桶的个数是数组最大值开方向下取整+1,与桶容量对应,桶容量与桶的乘积必须大于等于数组最大元素值)
const buckets = Array.from({ length: ~~Math.sqrt(maxValue) + 1 }, () => [])
// 把元素放入对应桶子
for (let i = 0; i < arr.length; i++) {
// 计算需要放入的桶的序号(元素值除以桶容量)
const index = ~~(arr[i] / ~~Math.sqrt(maxValue))
buckets[index].push(arr[i])
}
// 对每个桶内的元素进行排序
for (let i = 0; i < buckets.length; i++) {
// 此处选取插入排序, 空间消耗少,元素少常数时间消耗短
insertionSort(buckets[i])
}
// 使用rest参数把每个桶子数据合并
return [].concat(...buckets)
}
桶排序最好情况下使用线性时间O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。
将整数按位数切割成不同的数字,按每位分别分组即完成排序。不只是适用整数,也适用于字符串和特定格式的浮点数等
算法思想:
基数排序基于分别排序,分别收集,所以是稳定的。但基数排序的性能比桶排序要略差,
每一次关键字的桶分配都需要O(n)的时间复杂度,而且分配之后得到新的关键字序列又需要O(n)的时间复杂度。
假如待排数据可以以k为基数,d是最高位数(例如百位是3,千位是4),则基数排序的时间复杂度将是
O
(
k
∗
d
n
)
O(k*dn)
O(k∗dn),当然d要远远小于n,因此基本上还是线性级别的。
系数d可以省略,且无论数组是否有序,都需要从个位排到最大位数,所以时间复杂度始终为
O
(
k
∗
n
)
O(k*n)
O(k∗n) 。其中,n是数组长度,k为桶的数量。
基数排序的空间复杂度为 O ( n + k ) O(n+k) O(n+k),其中k为桶的数量。一般来说n>>k,因此额外空间需要大概n+k个左右
let radixSort = arr => {
let mod = 10 // 进制/基数,常见还有以radix为变量名
let dev = 1 // 用来取进制位数据
let maxDigit = 0 // 最大位数
let counter = []
// 获取最大位数
arr.forEach(item => {
let digit = item.toString().split('').length
maxDigit = digit > maxDigit ? digit : maxDigit
})
for (let i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
for (let j = 0; j < arr.length; j++) {
// 提取相应进制位的数据(个位/十位/百位...),相当于桶排序的桶的编号
let bucket = Math.floor((arr[j] % mod) / dev)
// 初始化统计数组
if (counter[bucket] == null) {
counter[bucket] = []
}
// 对应入组(这步相当于排序),利用LSD(次位优先)进行基数排序
counter[bucket].push(arr[j])
}
let pos = 0
for (let j = 0; j < counter.length; j++) {
let value = null
if (counter[j] != null) {
while ((value = counter[j].shift()) != null) {
arr[pos++] = value
}
}
}
// console.log('arr', arr) // 这里可以得到按个位、十位...排序结果
}
return arr
}
通过基数排序对数组{53, 3, 542, 748, 14, 214, 154, 63, 616}:

目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195
我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?
在我的用户模型中,我有一堆属性,例如is_foos_admin和is_bars_admin,它们决定允许用户编辑哪些类型的记录。我想干掉我的编辑链接,目前看起来像这样:'edit'ifcurrent_user.is_foos_admin?%>...'edit'ifcurrent_user.is_bars_admin?%>我想做一个帮助程序,让我传入一个foo或bar并返回一个链接来编辑它,就像这样:助手可能看起来像这样(这不起作用):defedit_link_for(thing)ifcurrent_user.is_things_admin?link_to'Edit',edit_poly
我有以下现有的Dog对象数组,它们按age属性排序:classDogattr_accessor:agedefinitialize(age)@age=ageendenddogs=[Dog.new(1),Dog.new(4),Dog.new(10)]我现在想插入一条新的狗记录,并将它放在数组中的正确位置。假设我想插入这个对象:another_dog=Dog.new(8)我想把它插入到数组中,让它成为数组中的第三项。这是一个人为的示例,旨在演示我特别想如何将一个项目插入到现有的有序数组中。我意识到我可以创建一个全新的数组并重新对所有对象进行排序,但这不是我的目标。谢谢!
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan
在字符串连接中,是否可以直接在语句中包含条件?在下面的示例中,我希望仅当dear列表不为空时才连接"mydear"。dear=""string="hello"+"mydear"unlessdear.empty?+",goodmorning!"但是结果报错:undefinedmethod'+'fortrue我知道另一种方法是在这条语句之前定义一个额外的变量,但我想避免这种情况。 最佳答案 使用插值而不是连接更容易和更具可读性:dear=""string="hello#{'mydear'unlessdear.empty?},goodmo
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
我有一个Ruby数组[1,4]。我想在中间插入另一个数组[2,3],这样它就变成了[1,2,3,4]。我可以使用[1,4].insert(1,[2,3]).flatten实现这一点,但是有更好的方法吗? 最佳答案 您可以通过以下方式进行。[1,4].insert(1,*[2,3])insert()方法处理多个参数。因此,您可以使用splat运算符*将数组转换为参数。 关于ruby-如何在数组中间插入一个数组?,我们在StackOverflow上找到一个类似的问题: