I am quite new in Julia and I don't know how to remove consecutive duplicates in an array. For example if you take this array :
`v=[8,8,8,9,5,5,8,8,1];`
I would like to obtain the vector v1 such that:
v1 = [8,9,5,8,1];
Could anyone help me? Many thanks.
One method could be to define:
function fastuniq(v)
v1 = Vector{eltype(v)}()
if length(v)>0
laste = v[1]
push!(v1,laste)
for e in v
if e != laste
laste = e
push!(v1,laste)
end
end
end
return v1
end
And with this function, you have:
julia> println(fastuniq(v))
[8,9,5,8,1]
But, when dealing with arrays, one need to decide if elements are to be deep or shallow copied. In case of integers, it doesn't matter.
In StatsBase.jl there is an rle function (Run-length encoding) that does exactly this.
This is a lot slower than #DanGetz's function but here is a way to do it in one line:
function notsofastunique(v)
return [v[1]; v[2:end][v[2:end] .!= v[1:end-1]]]
end
>println(notsofastunique(v))
[8,9,5,8,1]
Maybe it's useful for someone looking for a vecotrised solution.
In the spirit #niczky12 one-liner solution goal, the following uses Iterators.jl package (very useful and slowly migrating into Base).
using Iterators # install with Pkg.add("Iterators")
neatuniq(v) = map(first,filter(p->p[1]!=p[2],partition(chain(v,[nothing]),2,1)))
Have not done any benchmarks, but it should be OK (but slower than the longer for based function).
Just for the sake of practicing...
Here is another little function you can use to do this, this function will work for non negative values (inluding 0) only.
function anotherone(v)
v1 = zeros(eltype(v),length(v))
v1[1]=v[1]+1
for e = 2:length(v)
if v[e] != v[e-1]
v1[e] = v[e]+1
end
end
return v1[find(v1)]-1
end
edit:
Adding one more version, according to the input in the comments. I think this one should be even faster, maybe you could test it out :) This version should work for negative numbers as well.
function anotherone(v)
v1 = falses(length(v))
v1[1]=true
for e = 2:length(v)
if v[e] != v[e-1]
v1[e] = true
end
end
return v[v1]
end
Related
I am trying to save multiple solutions of my ODE in an Array. Right now this is what I got:
sols = []
for i in 1:numSim
if solver == "Rosenbrock23"
solution = solve(odeprob, Rosenbrock23())
append!(sols, solution)
end
end
As you can see I only want to append to this Array, if a certain ode solver is used. However, the "append!" statement neglects this statement and runs every iteration of the loop. I tried preallocating the array sol, to use a statement like this:sols[i] = solution
But here im struggling with the type declaration of the array sol.
I tried
sols = zeros(length)
and then
sols[i] = solution
However solution is of type ODESolution and can not be converted to Float64
Please provide adequate information to get an exact answer. I can't reproduce your problem since you didn't mention what is odeprob or the value of numSim. Since you declared sols = [] then the eltype of sols should be Any; hence it should be capable to contain any element.
However, I can replicate the code in the official doc (Example 1 : Solving Scalar Equations (ODE)), and combine it with your approach:
using DifferentialEquations
f(u,p,t) = 1.01*u
u0 = 1/2
tspan = (0.0,1.0)
odeprob = ODEProblem(f,u0,tspan)
sols = []
numSim = 2
solver = "Rosenbrock23"
for i in 1:numSim
if solver == "Rosenbrock23"
solution = solve(odeprob, Rosenbrock23())
append!(sols, solution)
end
end
Then if I call the sols variable:
julia> sols
22-element Vector{Any}:
0.5
0.5015852274675505
0.5177172276935554
0.5423763076371255
0.5852018498590001
0.6425679823795596
0.7275742030693312
0.835930076418226
0.9846257728490266
1.1713401410831334
1.3738764155543854
0.5
0.5015852274675505
0.5177172276935554
0.5423763076371255
0.5852018498590001
0.6425679823795596
0.7275742030693312
0.835930076418226
0.9846257728490266
1.1713401410831334
1.3738764155543854
I'm a little new to Julia and am trying to use the fill! method to improve code performance on Julia. Currently, I read a 2d array from a file say read_array and perform row-operations on it to get a processed_array as follows:
function preprocess(matrix)
# Initialise
processed_array= Array{Float64,2}(undef, size(matrix));
#first row of processed_array is the difference of first two row of matrix
processed_array[1,:] = (matrix[2,:] .- matrix[1,:]) ;
#last row of processed_array is difference of last two rows of matrix
processed_array[end,:] = (matrix[end,:] .- matrix[end-1,:]);
#all other rows of processed_array is the mean-difference of other two rows
processed_array[2:end-1,:] = (matrix[3:end,:] .- matrix[1:end-2,:]) .*0.5 ;
return processed_array
end
However, when I try using the fill! method I get a MethodError.
processed_array = copy(matrix)
fill!(processed_array [1,:],d[2,:]-d[1,:])
MethodError: Cannot convert an object of type Matrix{Float64} to an object of type Float64
I'll be glad if someone can tell me what I'm missing and also suggest a method to optimize the code. Thanks in advance!
fill!(A, x) is used to fill the array A with a unique value x, so it's not what you want anyway.
What you could do for a little performance gain is to broadcast the assignments. That is, use .= instead of =. If you want, you can also use the #. macro to automatically add dots everywhere for you (for maybe cleaner/easier-to-read code):
function preprocess(matrix)
out = Array{Float64,2}(undef, size(matrix))
#views #. out[1,:] = matrix[2,:] - matrix[1,:]
#views #. out[end,:] = matrix[end,:] - matrix[end-1,:]
#views #. out[2:end-1,:] = 0.5 * (matrix[3:end,:] - matrix[1:end-2,:])
return out
end
For optimal performance, I think you probably want to write the loops explicitly and use multithreading with a package like LoopVectorization.jl for example.
PS: Note that in your code comments you wrote "cols" instead of "rows", and you wrote "mean" but take a difference. (Not sure it was intentional.)
I have a variable as follows
local armies = {
[1] = "ARMY_1",
[2] = "ARMY_3",
[3] = "ARMY_6",
[4] = "ARMY_7",
}
Now I want to do an action for each value. What is the best way to loop over the values? The typical thing I'm finding on the internet is this:
for i, armyName in pairs(armies) do
doStuffWithArmyName(armyName)
end
I don't like that as it results in an unused variable i. The following approach avoids that and is what I am currently using:
for i in pairs(armies) do
doStuffWithArmyName(armies[i])
end
However this is still not as readable and simple as I'd like, since this is iterating over the keys and then getting the value using the key (rather imperatively). Another boon I have with both approaches is that pairs is needed. The value being looped over here is one I have control over, and I'd prefer that it can be looped over as easily as possible.
Is there a better way to do such a loop if I only care about the values? Is there a way to address the concerns I listed?
I'm using Lua 5.0 (and am quite new to the language)
The idiomatic way to iterate over an array is:
for _, armyName in ipairs(armies) do
doStuffWithArmyName(armyName)
end
Note that:
Use ipairs over pairs for arrays
If the key isn't what you are interested, use _ as placeholder.
If, for some reason, that _ placeholder still concerns you, make your own iterator. Programming in Lua provides it as an example:
function values(t)
local i = 0
return function() i = i + 1; return t[i] end
end
Usage:
for v in values(armies) do
print(v)
end
I am looking for something like list comprehensions in matlab however I couldnt find anything like this in the documentary.
In python it would be something like
A=[i/50 for i in range(50)]
Matlab is very fond of 'vectorizing'. You would write your example as:
A = (0:49) ./ 50
Matlab hates loops and therefore list comprehension. That said, take a look at the arrayfun function.
You can do:
(1:50)/50
Or for something more general, you can do:
f=#(x) (x/50);
arrayfun(f,1:50)
No, Matlab does not have list comprehensions. You really don't need it, as the focus should be on array-level computations:
A = (1:50) / 50
Matlab can work with arrays directly, making list comprehension less useful
If what you're trying to do is as trivial as the sample, you could simply do a scalar divide:
A = (0:50) ./ 50
There are several ways to generate a list in Matlab that goes from 0 to 49/50 in increments of 1/50
A = (0:49)/50
B = 0:1/50:49/50
C = linspace(0,49/50,50)
EDIT As Sam Roberts pointed out in the comments, even though all of these lists should be equivalent, the numerical results are different due to floating-point errors. For example:
max(abs(A-B))
ans =
1.1102e-16
This doesn't work help with your numerical example but for the special case of strings there is the compose function that does the same thing as a list comprehension of the form:
s = [f"Label_{i}" for i in range(1, 6)]
Example:
str = compose("Label_%d", 1:5)
Result:
str =
1×5 string array
"Label_1" "Label_2" "Label_3" "Label_4" "Label_5"
i was going through railstutorial and saw the following one liner
('a'..'z').to_a.shuffle[0..7].join
it creates random 7 character domain name like following:
hwpcbmze.heroku.com
seyjhflo.heroku.com
jhyicevg.heroku.com
I tried converting the one liner to groovy but i could only come up with:
def range = ('a'..'z')
def tempList = new ArrayList (range)
Collections.shuffle(tempList)
println tempList[0..7].join()+".heroku.com"
Can the above be improved and made to a one liner? I tried to make the above code shorter by
println Collections.shuffle(new ArrayList ( ('a'..'z') ))[0..7].join()+".heroku.com"
However, apparently Collections.shuffle(new ArrayList ( ('a'..'z') )) is a null
Not having shuffle built-in adds the most to the length, but here's a one liner that'll do it:
('a'..'z').toList().sort{new Random().nextInt()}[1..7].join()+".heroku.com"
Yours doesn't work because Collections.shuffle does an inplace shuffle but doesn't return anything. To use that as a one liner, you'd need to do this:
('a'..'z').toList().with{Collections.shuffle(it); it[1..7].join()+".heroku.com"}
It isn't a one-liner, but another Groovy way to do this is to add a shuffle method to String...
String.metaClass.shuffle = { range ->
def r = new Random()
delegate.toList().sort { r.nextInt() }.join()[range]}
And then you have something very Ruby-like...
('a'..'z').join().shuffle(0..7)+'.heroku.com'
This is my attempt. It is a one-liner but allows repetition of characters. It does not perform a shuffle, though it generates suitable output for a random domain name.
I'm posting it as an example of a recursive anonymous closure:
{ i -> i > 0 ? "${(97 + new Random().nextInt(26) as char)}" + call(i-1) : "" }.call(7) + ".heroku.com"
This is definitely not as pretty as the Ruby counterpart but, as Ted mentioned, it's mostly because of the fact that shuffle method is a static method in Collections.
[*'a'..'z'].with{ Collections.shuffle it; it }.take(7).join() + '.heroku.com'
I am using the spread operator trick to convert the range into a list :)