Search code examples
filtermapsxquerydeepequals

How to deep compare maps to filter distinct items in XQuery?


I wish I could filter a list of maps to remove those that are identical.

The union operator of XQuery only works on nodes. The

How can I do a deep comparison of maps to output distinct maps ? I can suppose that the function deep-equal() could be useful there with higher order function but I couldn’t cope with it.

let $map1 := map{ 
  'a' : '1',
  'b' : '2'
}
let $map2 := map{ 
  'c' : '3',
  'd' : '4'
}
let $map3 := map{ 
  'a' : '1',
  'b' : '2'
}
return local:getDistinctMap( ($map1, $map2, $map3) )

That should return

map{ 
  'a' : '1',
  'b' : '2'
}
map{ 
  'c' : '3',
  'd' : '4'
}

Solution

  • You can use fold-left:

    declare function local:getDistinctMaps($maps as map(*)*) as map(*)* {
      fold-left(
        $maps, 
        (),
        function($distinct-maps, $new-map) { 
          if (some $map in $distinct-maps satisfies deep-equal($map, $new-map))
          then $distinct-maps else ($distinct-maps, $new-map)
        }
      )
    };
    
    let $map1 := map{ 
      'a' : '1',
      'b' : '2'
    }
    let $map2 := map{ 
      'c' : '3',
      'd' : '4'
    }
    let $map3 := map{ 
      'a' : '1',
      'b' : '2'
    }
    return local:getDistinctMaps( ($map1, $map2, $map3) )