0

I wonder if there is a way to check if a value exists in an associative array in awk, I mean without knowing the corresponding key and without looping through all the array, like we would have in Python dict.values(). Let's take this example where the last if statement -if ("2" in array)- is FALSE and I don't know how to write it so it's TRUE.

echo -e 'a\na\nb' | \
awk '
    { array[$1] += 1 }
END {
    for (x in array){
        # key, key[value]
        print x, array[x]
    }
    if ("a" in array){
        # acces key
        print "OK for a key"
    }
    if ("2" == array["a"]){
        # access key[value]
        print "OK for a value when knowing the key"
    }
    if ("2" in array){
        # access value without knowing key ?
        print "OK for any value"}
    } else { 
        print "ERROR"
    }}'

Output:

a 2
b 1
OK for a key
OK for a value when knowing the key
ERROR

Is there a way to check if the array contains the values ("1" or "2" in this example) ?

Thanks !

2
  • 2
    Not possible without a loop Commented Jun 16, 2020 at 19:49
  • 2
    There is no uniqueness guarantee for the values, therefore you can never be sure which value (corresponding to which key) you have. If you don't care about uniqueness, you can create a reverse lookup array by swapping keys and values. Commented Jun 16, 2020 at 20:27

2 Answers 2

4

You can do something like this

$ echo -e 'a\na\nb' | 
  awk '{a[$1]++; b[a[$1]]=$1} 
   END {for(k in a) print k,a[k]; 
        for(k in b) print k,b[k]
        if(2 in b) print "2 is in values"}'

a 2
b 1
1 b
2 a
2 is in values

Note the second lookup b is by the values of the array a. However, the uniqueness comment is valid and if the values are not unique you'll miss the corresponding key in the reverse lookup. For just exist type check it might be fine.

Sign up to request clarification or add additional context in comments.

2 Comments

I didn't recognize what you were saying/doing til after I wrote my answer so mine is really a dup of yours (sorry!) and I'd normally just delete it as such but I'm not going to for now as I think it'll be clearer to the OP to see the same code structure they used tweaked to have the extra array and I think it might be clearer for the OP and others to see the longer array names.
No worries, your answers are more didactic, perhaps more useful in this case as well.
4

This is just showing the solution that @karakfa already mentioned applied to the OPs code so don't accept this answer, accept his instead.


You could keep a separate array indexed by values that you populate alongside your main associative array and test that:

$ echo -e 'a\na\nb' |
awk '
    { array[$1] += 1; arrvals[array[$1]] }
END {
    for (x in array){
        # key, key[value]
        print x, array[x]
    }
    if ("a" in array){
        # acces key
        print "OK for a key"
    }
    if ("2" == array["a"]){
        # access key[value]
        print "OK for a value when knowing the key"
    }
    if ("2" in arrvals){
        # access value without knowing key ?
        print "OK for any value"
    } else {
        print "ERROR"
    }
}'
a 2
b 1
OK for a key
OK for a value when knowing the key
OK for any value

The awk language is built on the premise that there should only be language constructs to do things that are difficult to do otherwise (which this obviously is not) - that's why awk is a tiny, simple, efficient, yet powerful language while others are bloated with unnecessary syntactic sugar.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.