首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何收集范围内的随机数列表?

如何收集范围内的随机数列表?
EN

Stack Overflow用户
提问于 2022-02-08 17:27:46
回答 3查看 77关注 0票数 -2

我有一个不符合8,9,10,25,47,48,49,50,51,52,53,54,55,102,107,111,201,202,203,204,205顺序的数字列表,对我来说,在范围内列出这个数字列表是非常重要的,比如:8-10,25,47-55,102,107,111,201-205,我熟悉shell脚本,但我找不到任何解决方案。

EN

回答 3

Stack Overflow用户

发布于 2022-02-09 22:19:13

由于只有shellbash被标记,下面是一个基于参数展开的bash解决方案

这在数字列表上迭代,每一个新的数字都相应地调整目标字符串的最后部分。

代码语言:javascript
运行
复制
list=
for n in 8 9 10 25 47 48 49 50 51 52 53 54 55 102 107 111 201 202 203 204 205; do
  a=${list##*,} b=${a#*-} c=${a%-*} list=${list%$a}
  if ((n > b+1)); then list+=$a,$n
  elif ((n > c)); then list+=$c-$n
  else list+=$n; fi
done
echo ${list:1}
代码语言:javascript
运行
复制
8-10,25,47-55,102,107,111,201-205
  • 如果您的数字存储在数组中,则循环执行,就像在for n in ${arrayvar[@]}; do中那样。
  • 如果输入是逗号分隔的数字字符串(类似于输出),则要么使用arrayvar=(${strvar//,/ })将其转换为数组,要么直接在转换for n in ${strvar//,/ }; do上迭代。
  • 如果您想在一个文件中排入其一行中的每个数字,请将for循环更改为while read -r n; do
  • 如果您需要首先对文件的内容进行排序,sort -n是最简单的方法。
  • 如果希望在数组中对其排序,可以使用mapfile -t arrayvar < <(printf '%s\n' "${arrayvar[@]}" | sort -n),或者按照这里IFS=$'\n' arrayvar=($(sort -n <<< "${arrayvar[*]}")); unset IFS中的解决方案进行排序。
票数 2
EN

Stack Overflow用户

发布于 2022-02-08 17:52:36

查找列表中的最小值和最大值。将所有数字作为键存储在关联数组中。然后,将所有数字从最小值迭代到最大值,如果数字-1不在关联数组中,则将开始一个新的范围。如果它在那里,范围继续,如果数字+1不在那里,范围就在这里结束。

代码语言:javascript
运行
复制
#! /bin/bash

list2ranges () {
    local -a arr
    IFS=, arr=($1)
    local min=${arr[0]}
    local max=${arr[0]}

    local -A seen
    local e
    for e in "${arr[@]}" ; do
        (( e < min )) && min=e
        (( e > max )) && max=e
        seen[$e]=1
    done

    local -a out
    local i
    for ((i=min; i<=max; ++i)) ; do
        if [[ ${seen[$i]} ]] ; then
            if [[ ${seen[$((i-1))]} ]] ; then
                if [[ ${out[${#out[@]}-1]} != *- ]] ; then
                    out[${#out[@]}-1]+=-
                fi
                if [[ ! ${seen[$((i+1))]} ]] ; then
                    out[${#out[@]}-1]+=$i
                fi
            else
                out+=($i)
            fi
        fi
    done
    IFS=, echo "${out[*]}"
}


list=8,9,10,25,47,48,49,50,51,52,53,54,55,102,107,111,201,202,203,204,205

diff <(list2ranges "$list") <(echo 8-10,25,47-55,102,107,111,201-205)

如果最小值和最大值之间的差值很大,这将需要很长的时间。考虑将Perl与套装:IntSpan一起使用。

代码语言:javascript
运行
复制
list=8,9,10,25,47,48,49,50,51,52,53,54,55,102,107,111,201,202,203,204,205
perl -MSet::IntSpan -wE 'say Set::IntSpan->new(shift)' -- "$list"
票数 1
EN

Stack Overflow用户

发布于 2022-02-10 04:17:35

好的,这是一个有趣的小问题,即使你没有显示你的最小、完全和可验证的示例(MCVE),它是值得增加另一种方法。

您可以通过保留两个标志(或状态)变量来简化此任务。10 (真或假)的简单变量,这些变量跟踪您是否已经写入了第一个值,以及您是否处于一个数字序列中,还是在序列号的范围之间。当您循环这些值时,如果您保留上次迭代中的最后一个值,则任务变得相当容易。

例如,您可以:

代码语言:javascript
运行
复制
#!/bin/bash

list=8,9,10,25,47,48,49,50,51,52,53,54,55,102,107,111,201,202,203,204,205

first=0     ## first value written flag
inseq=0     ## in sequence flag

while read -r n; do   ## read each of the sorted values
  ## if first not written, write, set last to current and set first flag
  [ "$first" -eq 0 ] && { printf "%s" "$n"; last="$n"; first=1; continue; }
  ## if current minus last is 1 -- in sequence, set inseq flag
  if ((n - last == 1)); then
    inseq=1
  elif [ "$inseq" -eq 1 ]; then         ## if not sequential
    printf -- "-%s,%s" "$last" "$n"     ## finish with last, output next
    inseq=0                             ## unset inseq flag
  else
    printf ",%s" "$n"                   ## individual number, print
  fi
  last="$n"                             ## set last to current
        ## process substitution sorts list with printf trick
done < <(IFS=$','; printf "%s\n" $list | sort -n)

## output final term either ending sequence or as individual number
if [ "$inseq" -gt 0 ]; then
  printf -- "-%s" "$last"
else
  printf ",%s" "$last"
fi

echo ""   ## tidy up with a newline

您可以声明您的数字不符合顺序,因此while()循环是由一个进程替换提供的,该进程在读取值之前用sort -n对值进行排序。(进程替换中未引用的$list是有意的)

示例使用/输出

代码语言:javascript
运行
复制
$ bash ranges.sh
8-10,25,47-55,102,107,111,201-205
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71038194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档