Mac下zsh列表遍历跳过项问题:代码缺陷排查
问题根源与解决方案
问题出在哪?
你用[[ $i < $j ]]做字符串字典序比较,但这种逻辑和你预期的「按Subject后缀数字大小判断顺序」完全不符:
- 字符串字典序中,"Subject10"会被判定为小于"Subject2"(因为字符'1'的ASCII码比'2'小),导致当
i是Subject2到Subject9时,j是Subject10到Subject19的情况下,比较条件不成立,不会输出你预期的正向组合; - 反过来,当
i是Subject10到Subject19时,j是Subject1到Subject9的情况下,条件成立,会输出反向组合(比如Subject10 - Subject1),但这种反向输出容易让你误以为对应组合被跳过; - 同时,双重循环全量遍历再过滤的方式效率不高,还容易因比较逻辑偏差产生问题。
最优解决方法:通过索引生成不重复两两组合
直接遍历列表的索引,让i从第一个元素到倒数第二个元素,j从i的下一个元素遍历到最后一个元素,天然生成所有不重复的正向两两组合,无需任何字符串比较:
subjects=(Subject1 Subject2 Subject4 Subject5 Subject6 Subject7 Subject8 Subject9 Subject10 Subject11 Subject12 Subject13 Subject14 Subject15 Subject16 Subject17 Subject18 Subject19 Subject20 Subject22 Subject23 Subject24 Subject25) len=${#subjects[@]} for ((i=0; i < len-1; i++)); do for ((j=i+1; j < len; j++)); do echo "Processing pair ${subjects[$i]} - ${subjects[$j]} ..." done done
备选方案:按数字大小比较字符串
如果一定要保留字符串遍历的方式,可以提取每个Subject名称后的数字,转成整数后再比较:
subjects=(Subject1 Subject2 Subject4 Subject5 Subject6 Subject7 Subject8 Subject9 Subject10 Subject11 Subject12 Subject13 Subject14 Subject15 Subject16 Subject17 Subject18 Subject19 Subject20 Subject22 Subject23 Subject24 Subject25) for i in "${subjects[@]}"; do num_i=$(( ${i#Subject} )) for j in "${subjects[@]}"; do num_j=$(( ${j#Subject} )) if (( num_i < num_j )); then echo "Processing pair $i - $j ..." fi done done
这里用"${subjects[@]}"遍历列表是更规范的写法,能避免元素包含特殊字符时出现意外问题。
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

