我有一个文件“ingredients.txt”,其中包含 38 个单词的列表(每行一个)。我已经弄清楚如何将其读入数组
getArray() {
array=()
while IFS= read -r line
do
array+=("$line")
done < "$1"
}
getArray "ingredients.txt"
但是现在如何从 38 个列表中输出恰好 4 个单词的所有组合?
编辑:为了回应评论,我的意思是组合而不是排列,并且重复无效。每个组合中有四个独特的单词。
为了进一步澄清,可以将其视为从袋子中抽取 4 个 38 种不同颜色的弹珠。没有两种颜色是一样的。一旦你抽出了一个红色的组合,就不可能再为该组合抽出另一个红色的组合。你画了四个,记下颜色,然后把它们放回袋子里,然后再画四个。如果您得到{蓝色,黄色,紫色,红色}和{黄色,紫色,红色,蓝色},则它们不会单独计算。我只想要组合,而不是排列。
另外,我想要打印每个组合(回到配料表):洋葱,奶酪,肉,生菜,胡萝卜,芹菜,萝卜胡萝卜,生菜,芹菜,醋等。
我希望这一点很清楚。
答案1
在Python中:
import itertools.combinations
with open('ingredients.txt') as fd:
words= fd.readlines()
for combination in itertools.combinations(words, 4):
print(combination)
答案2
我尝试使用 python
>>> a
['praveen', 'ajay', 'abhi', 'chetan', 'abh', 'cat']
for i in range(0,len(a),4):
... print a[i:i+4]
...
['praveen', 'ajay', 'abhi', 'chetan']
['abh', 'cat']
答案3
只是为了好玩,用普通 bash 编写的版本(我不建议在长列表中使用它,它非常慢(正如预期的那样),在 shell 中需要两分钟多才能完成 c 中完成的操作半秒。):
#!/bin/bash -
set -u
readarray -t b <ingredients.txt
r=${1:-3}
n=${2:-5}
main(){
combinations
}
combinations(){ : ${r:=3} ${n:=5} # default values
## The first line of elements is easy, fill an array of r elements:
for ((i=0 ; i<r ; i++)); do
a[i]=$i
done
printelements
## Up to the maximum permitted value of the first array element.
while (( a[0] < n-r )); do
## search backwards on the array for a value less than maximum.
for ((i = r-1; i >= 0; i--)); do
## If an item is below its maximum permitted value...
if ((a[i] < n-r+i )); then
## increment it:
((a[i]++))
break
fi
done
## Fill the rest of the array with consecutive values:
for (( i = i + 1 ; i < r ; i++ )); do
(( a[i] = a[i-1] + 1 ))
done
## Print the current combination of items:
printelements
done
}
printelements(){ : #p=${a[@]/%/ }; printf '%s\n' "<${p% }>"; }
s=""
for i in "${a[@]}"; do
printf '%s' "$s" "${b[i]}"
s=" "
done
echo
}
main
运行它作为:
$ ./script 4 38
将打印:
$ ./script 4 38 | wc -l
73815
正如数学所证实的那样(事实是库定义的函数):
$ bc <<<"r=4;n=38;fact(n)/(fact(r)*fact(n-r))" # n! / ( r! × (n-r)! )
73815
答案4
好吧,尝试使用下面的代码
getArray() {
array=()
while IFS= read -r line
do
array+=("$line")
done < "$1"
for i in ${!array[@]}
do
if [ ${#array[$i]} == 4 ]; then
echo "${array[$i]}"
fi
done
}
getArray "ingredients.txt"