performance - 从文件中选择随机行在 BASH 中花费的时间太长

标签 performance algorithm bash random

所以我有这个语法如下的脚本:

./script number file

其中 number 是我想从文件 file 中获取的行数。这些行是随机选择的,然后打印两次。考虑到一个非常大的文件 ~ 1 000 000 行,此算法运行速度太慢。我不知道为什么,因为打印只包含访问数组。

#!/bin/bash

max=`wc -l $2 | cut -d " " -f1`

users=(`shuf -i 0-$max -n $1`)
pages=(`shuf -i 0-$max -n $1`)

readarray lines < $2

for (( i = 0; i < $1; i++ )); do
    echo L ${lines[${users[i]}]} ${lines[${pages[i]}]} 
done

for (( i = 0; i < $1; i++ )); do
    echo U ${lines[${users[i]}]} ${lines[${pages[i]}]} 
done

最佳答案

只需使用 shuf 来选择行,这就是它的设计目的。例如(见注释):

readarray users < <(shuf -n $1 "$2")
readarray pages < <(shuf -n $1 "$2")
for (( i = 0; i < $1; i++ )); do
    echo L ${users[i]} ${pages[i]} 
done
for (( i = 0; i < $1; i++ )); do
    echo U ${users[i]} ${pages[i]} 
done

这仍然会很慢,因为 shuf 需要读取整个文件才能找到行尾,而且您要调用它两次,但它可能比读取将整个文件作为 bash 数组存入内存,尤其是当您没有足够的可用内存时。 (如果脚本的第二个参数不是常规文件,它也不会工作;如果它是管道,则不能读取它两次。)

您可以通过同时选择两组行然后将它们分为 userspages 来加快速度,但是您需要做一些工作才能获得无偏分布,假设您关心这一点。


注1:

正如@gniourf_gniourf 在评论中指出的那样,通过对 readarray 使用 -t 选项,然后将参数引用到回显。此外,mapfilereadarray 的首选名称:

mapfile -t users < <(shuf -n $1 "$2")
mapfile -t pages < <(shuf -n $1 "$2")
for (( i = 0; i < $1; i++ )); do
    echo L "${users[i]}" "${pages[i]}" 
done
for (( i = 0; i < $1; i++ )); do
    echo U "${users[i]}" "${pages[i]}"
done

注2:

如果 $1 很大,您最好不要使用数组。这是一种可能的解决方案:

lines="$(paste -d' ' <(shuf -n $1 "$2") <(shuf -n $1 "$"))"
sed 's/^/L /' <<<"$lines"
sed 's/^/U /' <<<"$lines"

关于performance - 从文件中选择随机行在 BASH 中花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26830677/

相关文章:

python - 如何通过 python 源脚本

bash - 试图在 Bash 的变量中嵌入换行符

linux - 通过脚本中的参数将多个文本文件连接到 Bash 中的单个文件中

string - 多文本比较算法

python - python中的LDA使用sklearn

javascript - JavaScript 中整数计算是否比实值计算提高性能?

DrRacket 编辑器的性能问题

algorithm - 玩家可以连续移动多次的 Minimax 树

php - 优化此 PHP 代码?

android - 如何增加 webrtc 中的麦克风增益