I've been playing around with arrays, and I don't understand where Nil is coming from and why the a[4] isn't being overwritten. Please see my example below.
a = Array.new
a[5] = '5';
a[0, 3] = 'a', 'b', 'c', 'd';
a[4] = 'hello'
template = ERB.new "<%= a %>"
puts template.result(binding)
Returns me the result
["a", "b", "c", "d", "hello", nil, "5"]
and
a = Array.new
a[4] = '5';
a[0, 3] = 'a', 'b', 'c', 'd';
a[4] = 'hello'
template = ERB.new "<%= a %>"
puts template.result(binding)
Returns me the result
["a", "b", "c", "d", "hello", "5"]
Thanks in advance for the help!
In Ruby when you say:
a[0, 3] = a, b, c
it means that starting from the index 0 start inserting 3 objects into the array. but if you say
a[0, 3] = a, b, c, d
since they are more than three elements, another element is inserted after the third object, therefore shifting 5 and its preceding nil to the next positions.
actually it's:
a[start, length]
not
a[start, end]
The problem (as Pedram explained while I typed this) is that a[0, 3] = 'a', 'b', 'c', 'd' does not replace values from a[0] to a[3]. It replaces 3 values beginning at a[0] (a[0], a[1], and a[2]), but since you are giving it 4 values, it inserts the fourth one as a new element after a[2].
If you want to use a range of indexes, use a[0..3]. Or you can use a[0, 4].
This is simple.
You are defining an Array which is empty at first. In Ruby, if you are inserting a value into an out-of-bound array it will fill all the other past indexes with nil.
For example, if I do:
a = []
a[9] = '10'
puts a
The output will be:
[nil, nil, nil, nil, nil, nil, nil, nil, nil, "10"]
All nine indexes before the one I inserted will be filled with nil. Which is the representation of nothing.
Related
I'm looking to pick a random key/value pair from a table, but using math.random() doesn't work.
--intialises randomization
math.randomseed(os.time()+30) --sets a random seed based on the time
math.random(); math.random(); math.random(); --clears presets
local phrases = {
["a"] = 3
["b"] = 7
["d"] = 4
["f"] = 8
["p"] = 5
}
local phrase = phrases[math.random(1,5)]
phrase would always output as nil. Is there a method of getting the index to use with math.random() or an alternate method I could use?
math.random(1, 5) returns numbers from 1 to 5. Your keys are strings.
You could create a table (as in: array - integer keys), get a random key from there and then access the phrases:
local phrases = {
["a"] = 3,
["b"] = 7,
["d"] = 4,
["f"] = 8,
["p"] = 5
}
local keys = {}
for k in pairs(phrases) do
table.insert(keys, k)
end
local random_key = keys[math.random(1,5)] -- One of: "a", "b", "d", "f", "p"
local phrase = phrases[random_key] -- One of: 3, 7, 4, 8, 5
I'm using Ruby 2.4 and Rails 5. I have an array of indexes within a line
[5, 8, 10]
How do I take the above array, and a string, and form anotehr array of strings that are split by the above indexes? FOr instance, if the string is
abcdefghijklmn
and split it based ont eh above indexes, I would have an array with the following strings
abcde
fgh
ij
klmn
Try this
str = "abcdefghijklmn"
positions = [5, 8, 10]
parts = [0, *positions, str.size].each_cons(2).map { |a, b| str[a...b] }
# => ["abcde", "fgh", "ij", "klmn"]
Or,
If the positions are constant and known ahead of runtime (for example if they were the format for a phone number or credit card) just use a regexp
str.match(/(.....)(...)(..)(.*)/).captures
# => ["abcde", "fgh", "ij", "klmn"]
This will get the Job done
str = "abcdefghijklmn"
arr_1 = [5, 8, 10]
arr_2, prev = [], 0
(arr_1.length + 1).times do |x|
if arr_1[x] == nil then arr_1[x] = str.size end
arr_2 << str[prev..arr_1[x] -1]
prev = arr_1[x]
end
p arr_2
---------------------------------------
Program Run Output
["abcde", "fgh", "ij", "klmn"]
---------------------------------------
I hope this Helps
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
There's two arrays of hash and I want remove the 'common' elements from the two arrays, based on certain keys. For example:
array1 = [{a: '1', b:'2', c:'3'}, {a: '4', b: '5', c:'6'}]
array2 = [{a: '1', b:'2', c:'10'}, {a: '3', b: '5', c:'6'}]
and the criteria keys are a and b. So when I get the result of something like
array1-array2 (don't have to overwrite '-' if there's better approach)
it will expect to get
[{a: '4', b: '5', c:'6'}]
sine we were using a and b as the comparing criteria. It will wipe the second element out since the value for a is different for array1.last and array2.last.
As I understand, you are given two arrays of hashes and a set of keys. You want to reject all elements (hashes) of the first array whose values match the values of any element (hash) of the second array, for all specified keys. You can do that as follows.
Code
require 'set'
def reject_partial_dups(array1, array2, keys)
set2 = array2.each_with_object(Set.new) do |h,s|
s << h.values_at(*keys) if (keys-h.keys).empty?
end
array1.reject do |h|
(keys-h.keys).empty? && set2.include?(h.values_at(*keys))
end
end
The line:
(keys-h.keys).empty? && set2.include?(h.values_at(*keys))
can be simplified to:
set2.include?(h.values_at(*keys))
if none of the values of keys in the elements (hashes) of array1 are nil. I created a set (rather than an array) from array2 in order to speed the lookup of h.values_at(*keys) in that line.
Example
keys = [:a, :b]
array1 = [{a: '1', b:'2', c:'3'}, {a: '4', b: '5', c:'6'}, {a: 1, c: 4}]
array2 = [{a: '1', b:'2', c:'10'}, {a: '3', b: '5', c:'6'}]
reject_partial_dups(array1, array2, keys)
#=> [{:a=>"4", :b=>"5", :c=>"6"}, {:a=>1, :c=>4}]
Explanation
First create set2
e0 = array2.each_with_object(Set.new)
#=> #<Enumerator: [{:a=>"1", :b=>"2", :c=>"10"}, {:a=>"3", :b=>"5", :c=>"6"}]
# #:each_with_object(#<Set: {}>)>
Pass the first element of e0 and perform the block calculation.
h,s = e0.next
#=> [{:a=>"1", :b=>"2", :c=>"10"}, #<Set: {}>]
h #=> {:a=>"1", :b=>"2", :c=>"10"}
s #=> #<Set: {}>
(keys-h.keys).empty?
#=> ([:a,:b]-[:a,:b,:c]).empty? => [].empty? => true
so compute:
s << h.values_at(*keys)
#=> s << {:a=>"1", :b=>"2", :c=>"10"}.values_at(*[:a,:b] }
#=> s << ["1","2"] => #<Set: {["1", "2"]}>
Pass the second (last) element of e0 to the block:
h,s = e0.next
#=> [{:a=>"3", :b=>"5", :c=>"6"}, #<Set: {["1", "2"]}>]
(keys-h.keys).empty?
#=> true
so compute:
s << h.values_at(*keys)
#=> #<Set: {["1", "2"], ["3", "5"]}>
set2
#=> #<Set: {["1", "2"], ["3", "5"]}>
Reject elements from array1
We now iterate through array1, rejecting elements for which the block evaluates to true.
e1 = array1.reject
#=> #<Enumerator: [{:a=>"1", :b=>"2", :c=>"3"},
# {:a=>"4", :b=>"5", :c=>"6"}, {:a=>1, :c=>4}]:reject>
The first element of e1 is passed to the block:
h = e1.next
#=> {:a=>"1", :b=>"2", :c=>"3"}
a = (keys-h.keys).empty?
#=> ([:a,:b]-[:a,:b,:c]).empty? => true
b = set2.include?(h.values_at(*keys))
#=> set2.include?(["1","2"] => true
a && b
#=> true
so the first element of e1 is rejected. Next:
h = e1.next
#=> {:a=>"4", :b=>"5", :c=>"6"}
a = (keys-h.keys).empty?
#=> true
b = set2.include?(h.values_at(*keys))
#=> set2.include?(["4","5"] => false
a && b
#=> false
so the second element of e1 is not rejected. Lastly:
h = e1.next
#=> {:a=>1, :c=>4}
a = (keys-h.keys).empty?
#=> ([:a,:c]-[:a,:b]).empty? => [:c].empty? => false
so return true (meaning the last element of e1 is not rejected), as there is no need to compute:
b = set2.include?(h.values_at(*keys))
So you really should try this out yourself because I am basically solving it for you.
The general approach would be:
For every time in array1
Check to see the same value in array2 has any keys and values with the same value
If they do then, delete it
You would probably end up with something like array1.each_with_index { |h, i| h.delete_if {|k,v| array2[i].has_key?(k) && array2[i][k] == v } }
I'm relatively new to the Lua language and there's something I'm obviously missing about table structures.
I'm trying to create a table of tables, with each table in the table having a key and the value being the respective table.
Ok, that statement can be confusing. Here's an example:
{{ key = "RC", value = {1, 2, 3, 4}},
{ key = "M", value = {4, 8, 7}},
{ key = "D", value = {3, 8, 9}}
...}
for this I used the following algorithm:
local listOfLists = {};
...
if condition1 then
listOfLists[key1] = list1;
end
...
if condition2 then
listOfLists[key2] = list2;
end
...
And so on...
I hope to use the keys to later determine which lists have been added to the table.
But the thing is, no lists seem to be added to the table even if all the conditions are met.
I can use table.insert(listOfLists, list1) in place of listOfLists[key1] = list1 but then I won't be able to tell which lists were added to the collection.
Ant suggestions?
Lua tables are a flexible data structure. Elements are key-value pairs. A key is any Lua value except nil. A value can have any value except nil. Assigning nil to the value obliterates the pair.
The (possibly empty) subset of a table that has key values of the number type that are integers from 1 to n is called a sequence. n is determined as the last such key that is paired with a nil value. Several table functions and operators work only with sequences.
Table constructors allow several syntaxes for keys:
Implied via a sequence: {1, 2, 3}
Explicit keys: {[1] = 1, [3] = 3, ["two"] = "value"}
Identifier keys: {one = 1, two = 2}
A table constructor can use any combination of them.
You have defined a sequence of elements, each of which is a table with two elements, the
second of which is a sequence.
It appears you want keys to be strings and values to be sequences:
{
RC = {1, 2, 3, 4},
M = {4, 8, 7},
D = {3, 8, 9}
}
It's hard to understand, what do you wanna achieve. So, if you want more specific answer, provide more info.
You can create associative table of tables.
local map = {}
map["key"] = { 1, 2, 3, 4 }
print(map.key[3])
Or you can create an array of tables
local vector = {}
vector[1] = { 1, 2, 3, 4 }
print(vector[1][2])
Or you can combine approaches.
To create
{{ key = "RC", value = {1, 2, 3, 4}},
{ key = "M", value = {4, 8, 7}},
{ key = "D", value = {3, 8, 9}}
...}
You can use table constructor or smth from code.
local tbl = { { key = "RC", value = {1, 2, 3, 4}} } -- init first elem from constructor
table.insert(tbl, { key = "M", value = {4, 8, 7}}) -- table insert & constructor
tbl[2] = {} -- Array-based access.
tbl[2].key = "D" --key access
tbl[2]["value"] = { 3, 8, 9 } -- other way
Note, that each table consists of two parts: vector for sequental keys from 1 to N, and map otherwise. Some functions, like table length operator or ipairs iterator are guaranteed to work only with vector-part of table. But they are significantly faster.
EDIT: (last paragraph explanation)
If you have a table with some keys and want to iterate through, you can use ipairs or pairs.
ipairs is ordered, and goes from 1 to first not-nil element. It doesn't iterate over not-integer keys. pairs goes trough any key, but doesn't guarantee order.
local map = { 1, 2, 3, key = 6, [5] = 5 }
for i, v in ipairs(map) do
print(v) -- will output 1, 2, 3. first nil element is map[4]. map[5] will mot be visited.
end
for i, v in pairs(map) do -- NOTE pairs usage
print(v) -- will output 1, 2, 3, 5, 6 in ANY order
end
map[4] = 4 -- Fill gap
for i, v in ipairs(map) do
print(v) -- will output 1, 2, 3, 4, 5. Now first nil element is map[6]
end
Length operator works similar to ipairs, it doesn't count elements not visited by ipairs method.
table.maxn works with numerical indices, and will return zero for your table.
Reference say that table.maxn
Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.)
Little example about length and table.maxn
local a = { 1, 2, 3, [5] = 5}
print(table.maxn(a)) -- 5
print(#a) -- 3
a = { key = 4 }
print(table.maxn(a)) -- 0
print(#a) -- 0
print(a["key"]) -- 4, nothing is lost
local num = 0
for _, __ in pairs(a) do num = num + 1 end
print(num) -- 1 We find it.
I have a variable called letters which in this instance equals the following:
["a", "e"]
Basically, how can I perform an active record query on my Item's model to find all Items that start with A, B, C, D & E?
Following this link: http://programming-tut.blogspot.ca/2009/10/ruby-on-rails-loop-alphabet-to-z.html
You could do that:
range = [ 'A', 'E' ]
conditions = (range.first..range.last).to_a.map{ |letter| " name ILIKE '#{letter}%' " }.join('OR')
Item.where(conditions)
Or like Vimsha pointed out:
letters = ('A'..'E').to_a
Item.where("substr(name, 1, 1) IN (?)", letters)
Item.where("substr(name, 1, 1) in ('A', 'B', 'C', 'D', 'E')")