skip to Main Content

I have 2 json files: a_names.json and b_names.json.
File a:

{
"Names": ["a","b","c"]
}

File b:

{
"Names": ["b","c"]
}

What i tried to do was (say i have a loop with counter ascending from 0):
a_names.Names | contains([b_names.Names[.counter]])
And the output is an error: Cannot index string with string.
However, next code provides a proper boolean output:
a_names.Names | contains(["b"])
My colleague said it’s happening due to me trying to refer to array 2 while being inside of the array 1, but we can’t find a solution.

P.S. – Same happens with any other "search" function, such as "any","IN", etc…

2

Answers


  1. Chosen as BEST ANSWER

    Solved:

    b_names.Names as $names | a_names.Names | contains([$names[.counter]])
    

    In order to work with 2 arrays at the same time you will need to initialize reference to both of them in separate pipes and only after that you can use functions.


  2. In the question, a_names is bound to the contents of the first file, whereas in practice the contents would more probably be bound to $a_names, so let’s assume you invoke jq as follows:

    jq -f program.jq a_names.json b_names.json
    

    In this case, a suitable program would be:

    . as $one
    | input as $two
    | all($one.Names[]; IN( $two.Names[] ))
    

    However, you may also wish to consider the following:

    jq -n '
      def a_names: { "Names": ["a","b","c"] } ;
      def b_names: { "Names": ["b","c"] } ;
    
      all(a_names.Names[]; IN( b_names.Names[] ))
    '
    

    Numerous other variants are possible, but I’d avoid contains in this case as its semantics is quite complex.


    If the arrays are known to have distinct items in strictly increasing order, or if the overhead of sorting them can be justified, then you could use subset/1 defined as:

    # Determine if the input is a subset of s2
    # where it is assumed both satisfy (. == unique)
    def subset($s2): 
      if length == 0 then true
      else .[0] as $x
      | ($s2 | bsearch($x) ) as $ix
      | if $ix < 0 then false
        else .[1:] | subset($s2[$ix+1:])
        end
      end;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search