s is hashes of array
relativebase = s.pluck(:base_point).inject(:+) + s.pluck(:distance_point).inject(:+) + s.pluck(:speed_point).inject(:+) + s.pluck(:frequency_point).inject(:+) + s.pluck(:quality_point).inject(:+)
This is calling the database four times which I want to do in one single query. How can i get this.
Something like:
User.select(:a, :b, :c, :d).all.inject([]) { |res, e| res << e.a; res << e.b; res << e.c; res << e.d; res }
Rails 4 supports multiple names in pluck:
relativebase = s.pluck(:base_point,
:distance_point,
:speed_point,
:frequency_point).inject(0) do |sum, (bp, dp, sp, fp)|
sum + bp + dp + sp + fp
end
Actually I personally think that it is probably better to calculate the sum in the database, but I'm not sure how to do that elegantly in rails:
SELECT SUM(base_point + distance_point + speed_point + frequency_point) FROM s
Related
I am searching for a solution to just and only consider real forex pairs in my loop. I don't want CFDs, commodities, silver, gold, etc. to be included because they have a complete different logic when it comes to calculating pips etc. etc. (I want to use the data for a FX dashboard).
How can I implement a filter to do so without building if-statements for every FX pair existing?
If possible, the solution should be independent of the broker used (since the offered FX pairs might be different from broker to broker, so a common approach would be the all-in solution).
This is my current code that doesn't seperate between fx and non fx:
/*
2.) Create a string format for each pending and running trade
*/
int live_orders = OrdersTotal();
string live_trades = "";
for(int i=live_orders; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS)==false) continue;
live_trades = live_trades +
"live_trades|" +
version + "|" +
DID + "|" +
AccountNumber() + "|" +
IntegerToString(OrderTicket()) + "|" +
TimeToString(OrderOpenTime(), TIME_DATE|TIME_SECONDS) + "|" +
TimeToString(OrderCloseTime(), TIME_DATE|TIME_SECONDS) + "|" +
IntegerToString(OrderType()) + "|" +
DoubleToString(OrderLots(),2) + "|" +
OrderSymbol() + "|" +
DoubleToString(OrderOpenPrice(),5) + "|" +
DoubleToString(OrderClosePrice(),5) + "|" +
DoubleToString(OrderStopLoss(),5) + "|" +
DoubleToString(OrderTakeProfit(),5) + "|" +
DoubleToString(OrderCommission(),2) + "|" +
DoubleToString(OrderSwap(),2) + "|" +
DoubleToString(OrderProfit(),2) + "|" +
"<" + OrderComment() + ">|";
}
This is probably the easiest way. Prefix symbols might be a problem (e.g. mEURUSD) but easily solved by shifting the StringSubstr values by the prefix size. Suffix is not a problem as we take the first 6 chars of the symbol string.
const string FX_CURRENCIES[]={"EUR","GBP","USD","NZD","AUD","CHF","CAD","JPY"};//add other currencies if needed
bool isFxPair(const string symbol){
return StringLen(symbol)>=6 && getCurrencyIdx(StringSubStr(symbol,0,3))>=0 &&
getCurrencyIdx(StringSubStr(symbol,3,3))>=0;
}
int getCurrencyIdx(const string smb){
for(int i=ArraySize(FX_CURRENCIES)-1;i>=0;i--){
if(FX_CURRENCIES[i]==smb)
return i;
}
return -1;
}
Use of CStringArray and caching FX symbols might be another good idea that may potentially work faster, but it seems to use the similar logic as above(but you'll have to sort the cache every time you add something in order to have CStringArray collection to work fast).
There is no direct method to ask whether a symbol is FX, CFD, Stock, Crypto or anything else.
I am trying to process the results of an array into a string to pass for a search. I want to build a string from the array that would look something like
("categories.name like '%Forms%' or categories.name like '%Apples%'")
serialize :category, JSON
if category.count > 1 && category.index != 0
$search_global.category.each do |cat_name|
cat_name.slice '" '
# cat_name
$array_count = $array_count + 1
if cat_name != ''
$inside_count = $inside_count +1
$cat_name_2 = "categories.name like %" + $cat_name_2 + cat_name + "% or " + $inside_count.to_s
end
end
end
If I select one item, it works fine as in
categories.name like %Forms% or 1
Please note that I am including the inside count just to get a better idea of what is happening.
The problem I have is when I select 2 or more items. categories.name like % is repeated twice and then the array items or listed as in
categories.name like %categories.name like %Calendar% or 1Forms% or 2
I can't seem to figure out why the concatenation isn't working as I expected.
$cat_name_2 = "categories.name like %" + $cat_name_2 + cat_name + "% or " + $inside_count.to_s
Your are using $cat_name_2 as the asignee as well as inside the assignment statement.
So I'm currently trying to sort values from a file. I'm stuck on the finding the first attribute, and am not sure why. I'm new to regex and ruby so I'm not sure how to go about the problem. I'm trying to find values of a,b,c,d,e where they are all positive numbers.
Here's what the line will look like
length=<a> begin=(<b>,<c>) end=(<d>,<e>)
Here's what I'm using to find the values
current_line = file.gets
if current_line == nil then return end
while current_line = file.gets do
if line =~ /length=<(\d+)> begin=((\d+),(\d+)) end=((\d+),(\d+))/
length, begin_x, begin_y, end_x, end_y = $1, $2, $3, $4, $5
puts("length:" + length.to_s + " begin:" + begin_x.to_s + "," + begin_y.to_s + " end:" + end_x.to_s + "," + end_y.to_s)
end
end
for some reason it never prints anything out, so I'm assuming it never finds a match
Sample input
length=4 begin=(0,0) end=(3,0)
A line with 0-4 decimals after 2 integers seperated by commas.
So it could be any of these:
2 4 1.3434324,3.543243,4.525324
1 2
18 3.3213,9.3233,1.12231,2.5435
7 9 2.2,1.899990
0 3 2.323
Here is your regex:
r = /length=<(\d+)> begin=((\d+),(\d+)) end=((\d+),(\d+))/
str.scan(r)
#=> nil
First, we need to escape the parenthesis:
r = /length=<(\d+)> begin=\((\d+),(\d+)\) end=\((\d+),(\d+)\)/
Next, add the missing < and > after "begin" and "end".
r = /length=<(\d+)> begin=\(<(\d+)>,<(\d+)>\) end=\(<(\d+)>,<(\d+)>\)/
Now let's try it:
str = "length=<4779> begin=(<21>,<47>) end=(<356>,<17>)"
but first, let's set the mood
str.scan(r)
#=> [["4779", "21", "47", "356", "17"]]
Success!
Lastly (though probably not necessary), we might replace the single spaces with \s+, which permits one or more spaces:
r = /length=<(\d+)>\s+begin=\(<(\d+)>,<(\d+)>\)\send=\(<(\d+)>,<(\d+)>\)/
Addendum
The OP has asked how this would be modified if some of the numeric values were floats. I do not understand precisely what has been requested, but the following could be modified as required. I've assumed all the numbers are non-negative. I've also illustrated one way to "build" a regex, using Regexp#new.
s1 = '<(\d+(?:\.\d+)?)>' # note single parens
#=> "<(\\d+(?:\\.\\d+)?)>"
s2 = "=\\(#{s1},#{s1}\\)"
#=> "=\\(<(\\d+(?:\\.\\d+)?)>,<(\\d+(?:\\.\\d+)?)>\\)"
r = Regexp.new("length=#{s1} begin#{s2} end#{s2}")
#=> /length=<(\d+(?:\.\d+)?)> begin=\(<(\d+(?:\.\d+)?)>,<(\d+(?:\.\d+)?)>\) end=\(<(\d+(?:\.\d+)?)>,<(\d+(?:\.\d+)?)>\)/
str = "length=<47.79> begin=(<21>,<4.7>) end=(<0.356>,<17.999>)"
str.scan(r)
#=> [["47.79", "21", "4.7", "0.356", "17.999"]]
Sample input:
length=4 begin=(0,0) end=(3,0)
data.txt:
length=3 begin=(0,0) end=(3,0)
length=4 begin=(0,1) end=(0,5)
length=2 begin=(1,3) end=(1,5)
Try this:
require 'pp'
Line = Struct.new(
:length,
:begin_x,
:begin_y,
:end_x,
:end_y,
)
lines = []
IO.foreach('data.txt') do |line|
numbers = []
line.scan(/\d+/) do |match|
numbers << match.to_i
end
lines << Line.new(*numbers)
end
pp lines
puts lines[-1].begin_x
--output:--
[#<struct Line length=3, begin_x=0, begin_y=0, end_x=3, end_y=0>,
#<struct Line length=4, begin_x=0, begin_y=1, end_x=0, end_y=5>,
#<struct Line length=2, begin_x=1, begin_y=3, end_x=1, end_y=5>]
1
With this data.txt:
2 4 1.3434324,3.543243,4.525324
1 2
18 3.3213,9.3233,1.12231,2.5435
7 9 2.2,1.899990
0 3 2.323
Try this:
require 'pp'
data = []
IO.foreach('data.txt') do |line|
pieces = line.split
csv_numbers = pieces[-1]
next if not csv_numbers.index('.') #skip the case where there are no floats on a line
floats = csv_numbers.split(',')
data << floats.map(&:to_f)
end
pp data
--output:--
[[1.3434324, 3.543243, 4.525324],
[3.3213, 9.3233, 1.12231, 2.5435],
[2.2, 1.89999],
[2.323]]
I am making a custom rails route as:
match '/setFavoriteRestaurant/:user_id/:restaurant_id/:campaignSetFav_id/:metro_id/:time_period', to: 'requests#setFavoriteRestaurant', via: 'get'
with controller action:
def setFavoriteRestaurant
setFavorite = "INSERT INTO androidchatterdatabase.users_favorite_restaurants(usersId,restaurantId,campaignIdSetFav,metroId,timePeriod,favoritedDt)
VALUES(" + params[:user_id].to_s + ","
+ params[:restaurant_id].to_s + ","
+ params[:campaignSetFav_id].to_s + ","
+ params[:metro_id].to_s + ","
+ params[:time_period].to_s + ",
NOW());"
ActiveRecord::Base.connection.execute(setFavorite)
end
Yet when testing in the browser with: http://localhost:3000/setFavoriteRestaurant/1/2/3/5/4
it returns an odd error as: undefined method +#' for "2":String
Why is this the case when other methods, setup exactly the same are fine to run?
This has to do with how you broke up the lines. Ruby doesn't know that the VALUES(" + line and the + params[:restaurant_id] are part of the same thing. This is because the VALUES( + line is complete. Move the + to the end of the line so that Ruby will know to expect the next line to be a continuation.
setFavorite = "INSERT INTO androidchatterdatabase.users_favorite_restaurants(usersId,restaurantId,campaignIdSetFav,metroId,timePeriod,favoritedDt)" +
"VALUES(" + params[:user_id].to_s + "," +
params[:restaurant_id].to_s + "," +
params[:campaignSetFav_id].to_s + "," +
params[:metro_id].to_s + "," +
params[:time_period].to_s + ",NOW());"
Also, note that I moved some other things around to avoid new lines and extra spaces.
I'm not sure why you prefer raw SQL here, but you should consider going through Rails. Seems like you're opening yourself up to SQL injection. At the very least, you could have some constraints in the route to match only integers.
Ruby has a couple of ways to quote multi line strings:
1) Here it is with ruby's heredoc syntax:
def some_action
setFavorite = <<-"END_OF_INSERT"
INSERT INTO androidchatterdatabase.users_favorite_restaurants(
usersId,
restaurantId,
campaignIdSetFav,
metroId,
timePeriod,
favoritedDt
)
VALUES(
"#{params[:user_id]}",
"#{params[:restaurant_id]}",
"#{params[:campaignSetFav_id]}",
"#{params[:metro_id]}",
"#{params[:time_period]}",
NOW()
);
END_OF_INSERT
end
Explanation:
setFavorite = <<-"END_OF_INSERT"
- => Terminator does not have to be at the start of the line.
"" => This is a double quoted string--do interpolation.
2) Here it is with %Q{}:
setFavorite = %Q{
INSERT INTO androidchatterdatabase.users_favorite_restaurants(
usersId,
restaurantId,
campaignIdSetFav,
metroId,
timePeriod,
favoritedDt
)
VALUES(
"#{params[:user_id]}",
"#{params[:restaurant_id]}",
"#{params[:campaignSetFav_id]}",
"#{params[:metro_id]}",
"#{params[:time_period]}",
NOW()
);
}
However, your SQL statement is still vulnerable to sql injection attacks. Check your db adapter for how to do parameter substitutions.
How can we achieve this in Ruby?
xs = [1,2,3]
x = 5
Then I need that sum = 1+2+3+1+2 = 9
You have the abstractions you need in the core, just wire them together: Enumerable#cycle, Enumerable#take and Enumerable#inject:
>> [1, 2, 3].cycle.take(5).inject(0, :+)
=> 9
That's the functional/declarative approach: use abstractions (either existing or those you implement yourself) so you can write code that describes what you are doing instead of how you are doing it.
def get_sum_cyclic(array, number)
sum = 0
0.upto(number - 1) do |i|
sum += array[i % array.size]
end
return sum
end
Another option is using map over a range:
(0...5).map{|i| a[i % a.size]}.inject(0){|t,v| t + v}
I don't think that there is a special way to do it in Ruby, but you can achieve this with the following snippet.
(0..x).inject(0) do |sum, i|
sum += arr[ i % arr.size ]
end