以相同顺序随机播放多个文件

时间:2014-03-05 19:33:38

标签: java linux bash random shuffle

设定:

我有50个文件,每个文件有25000行。

要-DO:

我需要“以同样的顺序”洗牌所有人。 E.g:

如果在洗牌之前:

File 1  File 2  File 3
A       A       A
B       B       B
C       C       C
然后在洗牌后我应该得到:

File 1  File 2  File 3
B       B       B
C       C       C
A       A       A

即。文件中的相应行应该以相同的顺序进行洗牌。

此外,shuffle应该是确定性的,即如果我将文件A作为输入,它应该总是产生相同的混洗输出。

我可以编写一个Java程序来完成它,可能是一个脚本。有点像,在1到25000之间洗牌,并将其存储在文件中,比如说shuffle_order。然后,一次只处理一个文件,并根据shuffle_order对现有行进行排序。但是有更好/更快的方法吗?

如果需要更多信息,请告诉我。

2 个答案:

答案 0 :(得分:1)

下一个只使用基本的bash命令。原则是:

  • 生成随机顺序(数字)
  • 按此顺序订购所有文件

代码

#!/bin/bash
case "$#" in
    0) echo "Usage: $0 files....." ; exit 1;;
esac

ORDER="./.rand.$$"
trap "rm -f $ORDER;exit" 1 2
count=$(grep -c '^' "$1")

let odcount=$(($count * 4))
paste -d" " <(od -A n -N $odcount -t u4 /dev/urandom | grep -o '[0-9]*') <(seq -w $count) |\
    sort -k1n | cut -d " " -f2 > $ORDER

#if your system has the "shuf" command you can replace the above 3 lines with a simple
#seq -w $count | shuf > $ORDER

for file in "$@"
do
    paste -d' ' $ORDER $file | sort -k1n | cut -d' ' -f2-  > "$file.rand"
done

echo "the order is in the file $ORDER"  # remove this line
#rm -f $ORDER                           # and uncomment this
                                        # if dont need preserve the order

paste -d "  " *.rand   #remove this line - it is only for showing test result

来自输入文件:

A  B  C
--------
a1 a2 a3
b1 b2 b3
c1 c2 c3
d1 d2 d3
e1 e2 e3
f1 f2 f3
g1 g2 g3
h1 h2 h3
i1 i2 i3
j1 j2 j3

A.rand B.rand C.rand使用下一个示例内容

g1 g2 g3
e1 e2 e3
b1 b2 b3
c1 c2 c3
f1 f2 f3
j1 j2 j3
d1 d2 d3
h1 h2 h3
i1 i2 i3
a1 a2 a3

真正的测试 - 用25k行生成50个文件

line="Consequatur qui et qui. Mollitia expedita aut excepturi modi. Enim nihil et laboriosam sit a tenetur."
for n in $(seq -w 50)
do
    seq -f "$line %g" 25000 >file.$n
done

运行脚本

bash sorter.sh file.??

结果在我的笔记本上

real     1m13.404s
user     0m56.127s
sys      0m5.143s

答案 1 :(得分:0)

可能非常低效,但请尝试以下:

#!/bin/bash

arr=( $(for i in {1..25000}; do
    echo "$i"
done | shuf) )


for file in files*; do
    index=0
    new=$(while read line; do
        echo "${arr[$index]} $line"
        (( index++ ))
    done < "$file" | sort -h | sed 's/^[0-9]\+ //')
    echo "$new" > "$file"
done