解剖这code,解释 - 检查是否另一个数组的数组子集 [英] dissecting this code, explanation - check if array subset of another array

查看:146
本文介绍了解剖这code,解释 - 检查是否另一个数组的数组子集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现这个例子在 wiki.bash-hackers.org ,但它不解释
细节,所以我在这里希望也许有人,可以把这个一些启示,并解释
发生了什么。

我理解 isSubset 函数的第一行,因为它正在通过指定参数时,使用间接
引用,商店钥匙进入内部数组 xkeys ykeys

第2线路设置参数,但我不明白什么 $ {@ /%/ [关键]} 是干什么的?
貌似替代,改变 [重点] ,我不知道这里发生了什么。

如果是,下一行它上的元素的数量相比较的阵列,但不应该它是反向,
返回1,如果一个数组有更多的元素,因为那时它不能被第二个子集?

最后 [[$ {2 + _!}&放大器;&安培; $ {!1} == $ {!2}]] ||返回1 ,为pretty混乱。

  isSubset(){
    当地-a'xkeys =($ {!'$ 1'[@]})''ykeys =($ {!'$ 2'[@]})'
    设置 - $ {@ /%/ [关键]}    (($ {#xkeys [@]}< = $ {#ykeys [@]}))||返回1    本地密钥
    在$ {xkeys [@]}键;做
        [[$ {2 + _!}&放大器;&安培; $ {!1} == $ {!2}]] ||返回1
    DONE
}主(){
    #一为b的一个子集
    当地-a'一=({} 0..5)''B =({0..10})
    isSubset A B
    回声$? #真    #一个包含一个键不在b的
    本地-a'一个=([5] = 5 {6..11})''B =({0..10})'
    isSubset A B
    回声$? #假    #一个中包含的元素,其值!=B的相应构件
    本地-a'一个=([5] = 5 6 8 9 10)''B =({0..10})'
    isSubset A B
    回声$? #假
}主要


解决方案

2号线:

  $ {@ /%/ [关键]}

作为模式的第一个字符表明图案具有匹配底。有没有在其他花纹所以意思是在年底更换空字符串,用'[关键]'。之后,位置参数是这样的:

  1 = A [关键]
    2 = B [关键]

下一行:


  

但它不应该是相反的,返回1,如果一个数组有更多的元素,


但做到这一点。请注意, || 运算符使用,所以它将返回 1 如果条件的满足。条件是:x.size< = y.size,所以它会返回 1 如果x.size> y.size

最后:

  [[$ {2 + _!}&放大器;&安培; $ {!1} == $ {!2}]] ||返回1

说实话,我不知道是什么 + _ 是。至于其他的,请注意,我们是在用变量循环。我们也有我们的位置的变量,所以:

  $ {!1}

变为

  $ {A [关键])

变量需要从阵列 A 键的值。所以整个测试验证,在给定的键值第二阵列中存在:

  [[$ {2 + _!}&放大器;&安培; ...

和与第一阵列在该密钥值是相同的,与所述第二阵列中的该密钥的值:

  ...&功放;&安培; $ {!1} == $ {!2}]

第一个条件是需要检测的情况下,当你通过数组 A 这在指数 I 有空字符串和阵列 b 不具有指数 I

 本地-a'A =([1] =2 3)'B =([2] = {2} 3..10)
isSubset A B
回声$? #假

I found this example at wiki.bash-hackers.org, however it is not explained in detail, so I was hoping maybe someone here, could put some light on this, and explain what is happening.

I understand the first line of isSubset function, as it is taking passed args, and using indirect referencing, stores keys into internal arrays xkeys and ykeys.

2nd line is setting parameters, but I don't understand what ${@/%/[key]} is doing? Looks like substitution, changing % to [key], I have no clue what happens here.

Then in next line it compares arrays on number of elements, but shouldn't it be reverse, returning 1 if first array has more elements, because then it can't be subset of the second one?

Finally [[ ${!2+_} && ${!1} == ${!2} ]] || return 1, is pretty confusing.

isSubset() {
    local -a 'xkeys=("${!'"$1"'[@]}")' 'ykeys=("${!'"$2"'[@]}")'
    set -- "${@/%/[key]}"

    (( ${#xkeys[@]} <= ${#ykeys[@]} )) || return 1

    local key
    for key in "${xkeys[@]}"; do
        [[ ${!2+_} && ${!1} == ${!2} ]] || return 1
    done
}

main() {
    # "a" is a subset of "b"
    local -a 'a=({0..5})' 'b=({0..10})'
    isSubset a b
    echo $? # true

    # "a" contains a key not in "b"
    local -a 'a=([5]=5 {6..11})' 'b=({0..10})'
    isSubset a b
    echo $? # false

    # "a" contains an element whose value != the corresponding member of "b"
    local -a 'a=([5]=5 6 8 9 10)' 'b=({0..10})'
    isSubset a b
    echo $? # false
}

main

解决方案

2nd line:

    ${@/%/[key]}

% as first character of the pattern indicates that pattern has to match at the end. There is nothing else in the pattern so the meaning is "replace empty string at the end, with '[key]'". After that positional parameters look like this:

    1 = a[key]
    2 = b[key]

Next line:

but shouldn't it be reverse, returning 1 if first array has more elements,

But it does that. Notice that || operator is used, so it will return 1 if the condition is not met. The condition is: "x.size <= y.size", so it will return 1 if "x.size > y.size".

Finally:

    [[ ${!2+_} && ${!1} == ${!2} ]] || return 1

To be honest, I don't know what +_ is for. As for the rest, notice that we are in a loop with a key variable. We also have key in our positional variables, so:

    ${!1}

becomes

    ${a[key])

and key variable takes values of keys from array a. So the whole test verifies that value with given key exists in the second array:

    [[ ${!2+_} && ...

and that value with that key in the first array is the same as the value with that key in the second array:

    ... && ${!1} == ${!2} ]]

The first condition is necessary to detect the case when you pass array a which at index i has empty string and array b which doesn't have index i:

local -a 'a=([1]="" 2 3)' 'b=([2]=2 {3..10})'
isSubset a b
echo $? # false

这篇关于解剖这code,解释 - 检查是否另一个数组的数组子集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆