Does Rego Set lookup will iterate all items in the set? - open-policy-agent

package example
default allow = false
input = {
"value_2": {"c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "a", "a"},
"value_1": ["c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "b", "c", "a", "a"]
}
allow {
input.value_1[_] == "a"
input.value_2["a"] == "a"
}
follow the example, which one will do the lookup faster?

Set lookup is constant time:
a_set["a"] # <-- this is constant time
Iteration and comparison of set elements is not (currently) optimized and is linear-time:
a_set[_] == "a" # <-- this is linear-time
The example above though is not valid because input.value_2 is defined as an array (not a set) so input.value_2["a"] is invalid. If you try this example you'll receive a type error from the compiler:
1 error occurred: policy.rego:12: rego_type_error: undefined ref: data.example.input.value_2.a
data.example.input.value_2.a
^
have: "a"
want (type): number
Assuming you wanted to use a set originally, just use the lookup syntax (s[k]) and do not bother with the additional equality check (unless you're testing for whether false is contained in the set, but that would be odd.)
Note, the Policy Reference page on the OPA website explains how to perform lookups, comparison, and iteration on arrays, objects, and sets.

Related

Show only 3 values in an array in ruby

I have included given code
#students = "All #{section.count}#{section.values}"
output: "All 9['A','B','C','D','E','F','G','H','I']"
But I want show output to be All 9['A','B','C',...]
Please guide me how to solve this. Thanks in advance.
You can print first 3 elements of Array and then manipulate the String to include ellipsis. Here:
section.values
# => ["A", "B", "C", "D", "E", "F", "G", "H", "I"]
puts "#{section.values[0..2]}".sub("]",", ...]")
# ["A", "B", "C", ...]
You can use #take method too. Example:
a = [1,2,3,4,5]
a.take(2) # will give as result [1,2]
Hope it will help.
You can do this
#students = "All #{section.count}#{(section.count > 3) ? (section.values[0..2] << '...') : section.values}"
Hope that helps!
first get all records and store it on #student.
and use first() method
#student.first(count)

Mapping a table column with values that persist on create and update in Rails

I have a column in the table that has string values for:
arr = ["First Name", "Last Name", "location", "Description"]
I need to map each of these values to letters sequentially:
["A", "B", "C", "D"]
These letters aren't part of the table and aren't defined, but I am leaning toward creating a small hash with the above arr, unless there is a better suggestion?
I need to be able to map each letter to its correspond value in the arr, and when the arr is updated in a view, each letter should correspond in the arr. For example, if the "First Name" is removed from the arr, then the first latter should be "B", or if the "location" is removed, then the new array should be "A", "B", "D". Meaning, on create or update, letters should always be mapped to corresponding values in the arr. I hope I am making sense?
Many thanks.
For example you have
arr = ["First Name", "Last Name", "location", "Description"]
arr_hash= Hash.new
and yout have a instance for
#client =Client.first
hash[0] = []
hash[0] << arr
hash[1] = []
hash[1] << #client
and more....
You can make hash with pairs first, and then remove keys that are not present in updated array.
arr = ["First Name", "Last Name", "location", "Description"]
arr2 = ["A", "B", "C", "D"]
result = Hash[arr.zip(arr2)]
# => {"First Name"=>"A", "Last Name"=>"B", "location"=>"C", "Description"=>"D"}
# update original arr like:
arr = ["Last Name", "location", "Description"]
result.delete_if { |k, _| !arr.include?(k) }
# => {"Last Name"=>"B", "location"=>"C", "Description"=>"D"}

Get an array of the values of a key from an array of hashes?

For an array like this:
a = [{a:'a',b:'3'},{a:'b',b:'2'},{a:'c',b:'1'}]
I would like to return an array containing values for :a keys, so:
['a', 'b', 'c']
That can be done using:
a.map{|x|x[:a]}
I wonder if there is a native method in Rails or Ruby to do it like this?
a.something :a
You can do it yourself:
class Array
def get_values(key)
self.map{|x| x[key]}
end
end
Then you can do this:
a.get_values :a
#=> ["a", "b", "c"]
More than you need in this case, but from How to merge array of hashes to get hash of arrays of values you can get them all at once:
merged = a.inject{ |h1,h2| h1.merge(h2){ |_,v1,v2| [*v1,*v2] } }
p merged[:a] #=> ["a", "b", "c"]
p merged[:b] #=> ["3", "2", "1"]
Also, if you use something like Struct or OpenStruct for your values instead of hashes—or any object that allows you to get the "a" values as a method that does not require parameters—you can use the Symbol#to_proc convenience for your map:
AB = Struct.new(:a,:b)
all = [ AB.new('a','3'), AB.new('b','2'), AB.new('c','1') ]
#=> [#<AB a="a", b="3">, #<AB a="b", b="2">, #<AB a="c", b="1">]
all.map(&:a) #=> ["a", "b", "c"]
all.map(&:b) #=> ["3", "2", "1"]

What is the difference between the "sort" and "sort!" method in ruby? [duplicate]

This question already has answers here:
Why are exclamation marks used in Ruby methods?
(12 answers)
Closed 8 years ago.
From Ruby's official documentation:
sort → new_ary sort { |a, b| block } → new_ary Returns a new array
created by sorting self.
Comparisons for the sort will be done using the <=> operator or using
an optional code block.
The block must implement a comparison between a and b, and return -1,
when a follows b, 0 when a and b are equivalent, or +1 if b follows a.
See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort #=> ["a", "b", "c", "d", "e"]
a.sort { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
sort! → ary click to toggle source sort! { |a, b| block } → ary Sorts
self in place.
Comparisons for the sort will be done using the <=> operator or using
an optional code block.
The block must implement a comparison between a and b, and return -1,
when a follows b, 0 when a and b are equivalent, or +1 if b follows a.
See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort! #=> ["a", "b", "c", "d", "e"]
a.sort! { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
The result seems the same, so what's the difference?
sort will not modify the original array whereas sort! will
('!' is the bang method in ruby, it will replace the existing value)
For example:
a = [4,3,2,5,1]
a.sort # => [1,2,3,4,5]
a is still [4,3,2,5,1]
where as
a = [4,3,2,5,1]
a.sort! # => [1,2,3,4,5]
a is now [1,2,3,4,5]
In rails ! used to apply changes and update its calling object means
a.sort will only return sorted array but a.sort! will return sorted array and also save new sort result in a variable.
'!' is the bang method in ruby, it will replace the existing value
ex: .sort is a normal sorting method in ruby
.sort! its a bang method in ruby its override the existing value.

Ruby array manipulation (Ruby 1.8 and Rails 2.2)

I'm hopelessly trying to write a method to manipulate an array in ruby. I'm trying to generate all in-order permutations of an array where each item is in turn replaced by an outside item. An example...
Given input:
arr = ["a", "b", "c"]
Desired output:
newArr = [ ["a", "b", "c"], ["a", "b", "*"], ["a", "*", "c"], ["a", "*", "*"], ["*", "b", "c"], ["*", "b", "*"], ["*", "*", "c"], ["*", "*", "*"] ]
Any help would be greatly appreciated. Thank you!
I don't understand your example order, either, but ignoring that, here's a solution in one line:
(0...(2**a.size)).map {|x| (0...a.size).map {|y| x & 2**y == 0 ? a[y] : val}}
I'm not sure permutation is the right word. If you count in binary, then you are replacing the things if there is a one. Here's that in Ruby:
def mike(arr, sub)
format = sprintf("%%0%db", arr.length)
m = Array.new
0.upto(2**arr.length-1) { |i|
bits = sprintf(format, i).split('')
a = Array.new
0.upto(arr.length-1) { |j|
if bits[j] == '0' then
a << arr[j]
else
a << sub
end
}
m[i] = a
}
return m
end
arr = ["a", "b", "c"]
p mike(arr, '*')
Is that if-then-else better with a ternary operator?
a <<= bits[j] == '0' ? arr[j] : sub
There must be a cleverer (or, at least more Rubyesque) way to do this, but it seems to produce the desired output.
ETA: Oops! My second and third items don't agree with yours. I guess I don't know what order you mean.
Similar to oylenshpeegui's method:
def toggle(arr, sub)
format = "%0#{arr.length}b"
(0...2**(arr.length)).to_a.map do |i|
sprintf(format,i).split('').zip(arr).map { |x| x[0] == "0" ? x[1] : sub }
end
end
The split/zip combo matches each digit of the binary expansion of the index with the element it is selecting. The map at the end uses the digit to decide if it should return the array element or the substitution.

Resources