I want to compare just the time part of different datetimes.
the result gives me false, but it should be true. what am I missing here?
is there a better way to do it.
this is what I tried, and the logic seems to fail:
let current_future = format_datetime(now(+2h), 'HH:m:s.fff');
//print current_future
let current_past = format_datetime(now(-1h), 'HH:m:s.fff');
//print current_past
let result = iff((todatetime(current_past) < todatetime(current_future)), "true", "false");
print result ```
To extract the time from a datetime value, you should do % 1d.
let x = datetime(2022-01-23 09:55:16);
let y = datetime(2022-01-21 19:55:16);
print x<y, (x%1d) < (y%1d)
Result:
print_0
print_1
False
True
You could use timespan.
let t1 = datetime(2022-01-01 23:44:55);
let t2 = datetime(2022-02-01 08:22:33);
print (t1 - bin(t1,1d)) < (t2 - bin(t2,1d))
Your solution is problematic since you are not using 2 digits hour and alphabetically '8' (like in 8:22:33) is bigger than '23' (like in 23:44:55)
Related
I would like to know if there will be a way to transform a csv to the JSON format suitable for the Tabulator library?
The idea would be to have a format as seen on excel :
- the first cell on the top left, empty
- columns A, B, C... AA, AB... according to the number of cells on the longest row
- the line number automatically on the first cell of each line)
I had the idea of doing it directly with loops, but it takes a lot of time I find. I don't see any other way.
Thank you for the help.
Check the following function, I hope this is what you are looking for...
let csvfile = 'title1,title2,title3,title4\n1,2,3,4\n11,22,33,44' //YOUR CSV FILE
let capLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' // ALPHABET SET
let finalJson = [];
let headers;
let line =[];
convertCSV2JSON(csvfile)
function convertCSV2JSON(csv) {
line = csv.split("\n"); //PARSE ALL AVAILABLE LINES INTO ARRAY
result = [];
headers = line[0].split(","); //PARSE ALL AVAILABLE STRING NAMES INTO ARRAY AND KEEP ONLY THE FIRST ONE (HEADER)
line.slice(1).forEach(function(item,i){ //RUN EACH ITEM EXCLUDING COLUMN NAMES
var obj = {};
if(line[i] === null || line[i] === undefined) {
}else{
var entries = line[i+1].split(","); // SEPARATE FOUND ENTRIES EXCLUDING COLUMN NAMES (i+1)
for(var j = 0; j < entries.length; j++) { // PARSE ENTRIES
obj[convert2Letters(j)] = entries[j]; // ASSIGN A LETTER AS COLUMN NAME
}
}
finalJson.push(obj);
})
console.log(finalJson);
}
function convert2Letters(iteration) {
let readyLetter = ''
while (iteration >= 0) {
readyLetter += capLetters[iteration % 26]
iteration = Math.floor(iteration / 26) - 1
}
return readyLetter
}
The fuzzy part was at foreach() function, because you cannot initiate index at your preference... slice() did the trick!
Moreover convert2Letters() function takes an array of letters and on each iteration finds the modulus of 26 letters, removing by one shows you the next combination...
Example:
If you have 30 columns it will give 30 % 26 = 4
4 corresponds to capLetters[4] which is 'E'
calculate next: iteration = Math.floor(iteration / 26) - 1 which means on every 26 increment (0,26,52,78...) it will give (-1,0,1,2...) corresponding. So a 30 columns iteration will have 0 as result which corresponds to capLetters[0] = 'A'
Resulting: 30 columns will give letters 'EA'
I'm quite new to Rust and Diesel. I'm now trying to implement Diesel filtering for query like this:
-- #param1 is duration in years
-- #param2 is duration in months
SELECT columns FROM a
WHERE
(...dynamic AND clauses)
AND (((a.min_unit = "Years") AND (a.min_duration <= #param1))
OR ((a.min_unit = "Months") AND (a.min_duration <= #param2)))
(...dynamic AND clauses)
After some searches in docs and around the web, I still couldn't find how to do this.
My closest guess is:
let param1 = ...;
let param2 = ...;
let mut query = a::table.select(a::all_columns).into_boxed();
// dynamic clauses: query = query.filter(...) ...
query = query.filter(a::min_unit.eq(Some("Years")).and(a::min_duration.le(Some(param1))))
.or_filter(a::min_unit.eq(Some("Months")).and(a::min_duration.le(Some(param2))));
// dynamic clauses: query = query.filter(...) ...
let results = a::table.load<A>(&*conn);
Anyone has idea?
Thanks!
Your code actually looks correct (I haven't run it). The documentation here points to how it is done: https://docs.diesel.rs/diesel/query_dsl/trait.QueryDsl.html#method.or_filter foo.filter(bar).or_filter(baz) is like foo.filter(bar.or(baz)) but the second one is "nested". So, to get
(id = 5 OR other = 6) AND foo=7
one would do
.filter(id.eq(5).or(other.eq(6))).filter(foo.eq(7)).
Hope that helps!
Well, here is my latest try:
let min_months_predicate = a::min_unit.eq(Some("Months"))
.and(a::min_duration.le(Some(param1)));
let min_years_predicate = a::min_unit.eq(Some("Years"))
.and(a::min_duration.le(Some(param1)));
query = query.filter(min_months_predicate.or(min_years_predicate))
.filter(a::max_duration.ge(Some(param2)));
debug!("TEST QUERY: {:?}", debug_query(&query));
which yields this query:
"SELECT \"a\".\"id\", \"a\".\"code\", .... WHERE (\"a\".\"min_unit\" = $1 AND \"a\".\"min_duration\" <= $2 OR \"a\".\"min_unit\" = $3 AND \"a\".\"min_duration\" <= $4) AND \"a\".\"max_duration\" >= $5"
And when I use sql EXPLAIN with this query, I got this clause:
Filter: ((max_duration >= 60) AND (((min_unit = 'Months'::text) AND (min_duration <= 3)) OR ((min_unit = 'Years'::text) AND (min_duration <= 5))))
which seems correct.
In [3, 2, 1, 1, 1, 0], if the value we are searching for is 1, then the function should return 2.
I found binary search, but it seems to return the last occurrence.
I do not want a function that iterates over the entire vector and matches one by one.
binary_search assumes that the elements are sorted in less-to-greater order. Yours is reversed, so you can use binary_search_by:
let x = 1; //value to look for
let data = [3,2,1,1,1,0];
let idx = data.binary_search_by(|probe| probe.cmp(x).reverse());
Now, as you say, you do not get the first one. That is expected, for the binary search algorithm will select an arbitrary value equal to the one searched. From the docs:
If there are multiple matches, then any one of the matches could be returned.
That is easily solvable with a loop:
let mut idx = data.binary_search_by(|probe| probe.cmp(&x).reverse());
if let Ok(ref mut i) = idx {
while x > 0 {
if data[*i - 1] != x {
break;
}
*i -= 1;
}
}
But if you expect many duplicates that may negate the advantages of the binary search.
If that is a problem for you, you can try to be smarter. For example, you can take advantage of this comment in the docs of binary_search:
If the value is not found then Result::Err is returned, containing the index where a matching element could be inserted while maintaining sorted order.
So to get the index of the first value with a 1 you look for an imaginary value just between 2 and 1 (remember that your array is reversed), something like 1.5. That can be done hacking a bit the comparison function:
let mut idx = data.binary_search_by(|probe| {
//the 1s in the slice are greater than the 1 in x
probe.cmp(&x).reverse().then(std::cmp::Greater)
});
There is a handy function Ordering::then() that does exactly what we need (the Rust stdlib is amazingly complete).
Or you can use a simpler direct comparison:
let idx = data.binary_search_by(|probe| {
use std::cmp::Ordering::*;
if *probe > x { Less } else { Greater }
});
The only detail left is that this function will always return Err(i), being i either the position of the first 1 or the position where the 1 would be if there are none. An extra comparison is necessary so solve this ambiguity:
if let Err(i) = idx {
//beware! i may be 1 past the end of the slice
if data.get(i) == Some(&x) {
idx = Ok(i);
}
}
Since 1.52.0, [T] has the method partition_point to find the partition point with a predicate in O(log N) time.
In your case, it should be:
let xs = vec![3, 2, 1, 1, 1, 0];
let idx = xs.partition_point(|&a| a > 1);
if idx < xs.len() && xs[idx] == 1 {
println!("Found first 1 idx: {}", idx);
}
let len = 25000000
let map = Map.ofArray[|for i =1 to len do yield (i,i+1)|]
let maparr = [|map;map;map;map|]
let f1 i =
for i1 =1 to len do
let l1 = maparr.[i-1].Item(i1)
()
let index = [|1..4|]
let _ = index |> Array.Parallel.map f1
printf "done"
I found that only one core is working at full speed be the code above . But what i except is all the four thread is working together with a high level of cpu usage. So it seems multithread conflict with Map, am i right? If not, how can achieve my initial goal? Thank you in advance
So I think you were tripping a heuristic where the library assumed when there were only a small number of tasks, it would be fastest to just use a single thread.
This code maxes out all threads on my computer:
let len = 1000000
let map = Map.ofArray[|for i =1 to len do yield (i,i+1)|]
let maparr = [|map;map;map;map|]
let f1 (m:Map<_,_>) =
let mutable sum = 0
for i1 =1 to len do
let l1 = m.Item(i1)
for i = 1 to 10000 do
sum <- sum + 1
printfn "%i" sum
let index = [|1..40|]
printfn "starting"
index |> Array.map (fun t -> maparr.[(t-1)/10]) |> Array.Parallel.iter f1
printf "done"
Important changes:
Reduced len significantly. In your code, almost all the time was spent creating the matrix.
Actually do work in the loop. In your code, it is possible that the loop was optimised to a no-op.
Run many more tasks. This tricked the scheduler into using more threads and all is good
I want the last character from a string
I've got str.[str.Length - 1], but that's ugly. There must be a better way.
There's no better way to do it - what you have is fine.
If you really plan to do it a lot, you can author an F# extension property on the string type:
let s = "food"
type System.String with
member this.Last =
this.Chars(this.Length-1) // may raise an exception
printfn "%c" s.Last
This could be also handy:
let s = "I am string"
let lastChar = s |> Seq.last
Result:
val lastChar : char = 'g'
(This is old question), someone might find this useful, orig answer from Brian.
type System.String with
member this.Last() =
if this.Length > 1 then
this.Chars(this.Length - 1).ToString()
else
this.[0].ToString()
member this.Last(n:int) =
let absn = Math.Abs(n)
if this.Length > absn then
let nn =
let a = if absn = 0 then 1 else absn
let b = this.Length - a
if b < 0 then 0 else b
this.Chars(nn).ToString()
else
this.[0].ToString()
"ABCD".Last() -> "D"
"ABCD".Last(1) -> "D"
"ABCD".Last(-1) -> "D"
"ABCD".Last(2) -> "C"
You could also treat it as a sequence, but I'm not sure if that's any more or less ugly than the solution you have:
Seq.nth (Seq.length str - 1) str