So I started using Julia, and I wonder if you can find a character in a string. For example:
x = "hello."
looks for a . (if it is there)
removes the .
x = "hello"
my program based on the answers (works now!):
# hello.jl
# --- Greeting ---
println("Hello!")
println("How are you?")
# --- Input ---
x = readline()
# --- Put the characters in the ' ' for use later ---
removechar = ['.', '!', '*', '(', ')',' ']
# --- Fixing ---
fixedX = replace(lowercase(x), removechar => "")
# --- Print Answer ---
println("I'm ", fixedX, " too!")
You can use replace to replace characters in a string (even if those characters are not in the string):
julia> replace("hello.", "." => "")
"hello"
julia> replace("world", "." => "")
"world"
If you just want a boolean indicating whether a sub-string exists in a string, you can use contains or occursin:
julia> contains("the quick brown fox", "fox")
true
julia> occursin("fox", "the quick brown fox")
true
contains and occursin are basically the same, except the argument order is reversed. You can remember the argument order by reading the function name in between the two arguments, like this:
contains(x, y): "x contains y"
occursin(x, y): "x occurs in y"
You can replace several characters at once (I understand this is what you want) with the following replace syntax:
julia> replace("hello.", ['.', 'o','e'] => "")
"hll"
Related
I have a dataframe with a column text that a is a list of strings, like this:
text
["text1","text2"]
["text3","text4"]
How can I clean de string to have another column text_clean like this:
text
text1,text2
text3,text4
When I type in repl df I get:
text
String
["string"]
["string","anotherestring"]
but when I type:
df[!,:text]
I get:
"[\"string\"]"
"[\"string\",\anotherestring\"]"
I would like to create a new dolumn, called text_clean:
string
string, anotherstring
Thanks
julia> a = [["text", "text2"], ["text"], ["text", "text2", "text", "text2"]]
3-element Vector{Vector{String}}:
["text", "text2"]
["text"]
["text", "text2", "text", "text2"]
julia> join.(a, ",")
3-element Vector{String}:
"text,text2"
"text"
"text,text2,text,text2"
replace a with your column, like df.text
It seems that your strings literally have values containing [s, "s, etc.
First of all, make sure that this is intended. For eg., you might have something like a vec = ["string", "anotherstring"]. At some point before this, you might have code doing the equivalent of df[1, :text] = string(vec). Instead, do df[1, :text] = join(vec, ", ") when assigning to the text column, to have that original column itself be clean.
If the above doesn't apply, and you have to deal with the column as given, then you create your new cleaned column like this:
julia> df = DataFrame(:text => [string(["hello", "world"]), string(["this","is","SPARTA"])])
2×1 DataFrame
Row │ text
│ String
─────┼──────────────────────────
1 │ ["hello", "world"]
2 │ ["this", "is", "SPARTA"]
julia> df[!, :text_clean] = map(df.text) do str
str |>
s -> strip(s, ('[', ']')) |> #remove [ ]
s -> strip.(split(s, ", "), '"') |> # remove inner "
sv -> join(sv, ", ")
end
2-element Vector{String}:
"hello, world"
"this, is, SPARTA"
(You might have to adjust the second argument to split above based on whether or not you have a space after the commas in the text column.)
Or, making use of Julia's own syntax parsing,
julia> df[!, :text_clean] = map(df.text) do str
str |> Meta.parse |>
ex -> ex.head == :vect && eval(ex) |>
sv -> join(sv, ", ")
end
2-element Vector{String}:
"hello, world"
"this, is, SPARTA"
(The ex.head == :vect is a basic sanity check to make sure that the string is in the format you expect, and not anything malicious, before evaluating it.)
I am a Julia (and stackoverflow) newbie but am trying unsuccessfully to simplify a function call.
I need to define calls to create many instances of 30 different structs, each having a different set of properties.
The code below works but will force the user to use exactly the same string twice, as in:
EV_668876 = newEV("EV_668876", "test EV")
This is a pain and likely to cause errors.
I have written a macro to generate the command but can't get REPL to execute the command.
Here is the code (sorry for its length).
mutable struct EV
label::FixedLabel
id::FixedId
name::String
designAuth::Ident
descripn::String
timestamp::String
priority::Int16
assoc_EO::Ident # this needs a new Set of EOstructs, to be defined
origin_OV::Ident # similar Set of OVstructs
OV_destination::Ident # this needs a new OVstruct, to be defined
underRespOf::Ident
underAuthOf::Ident
end
function newEV(id::String, name::String)
trylabel = String(split(id,['-',':','_'])[1]) # Note that split() yields a SubString(String)
if trylabel !== "EV" # ! => not
throw(DomainError("This id $id is not an EV, try again"))
end
labelFixed = FixedLabel(trylabel)
registerId(id) # registers id if OK
idFixed = FixedId(id)
# ident = newId(id,name)
new = EV(labelFixed,idFixed,name,anon_anon,"","",0,anon_anon,anon_anon,anon_anon,anon_anon,anon_anon)
end
EV_668876 = newEV("EV_668876", "test EV") # runs OK and produces
#=
This runs OK and produces
EV_668876 registered OK
EV(FixedLabel("EV"), FixedId("EV_668876"), "test EV", Ident(FixedLabel("PPR"), FixedId("PPR-2"), "Anon_Anon"), "", "", 0, Ident(FixedLabel("PPR"), FixedId("PPR-2"), "Anon_Anon"), Ident(FixedLabel("PPR"), FixedId("PPR-2"), "Anon_Anon"), Ident(FixedLabel("PPR"), FixedId("PPR-2"), "Anon_Anon"), Ident(FixedLabel("PPR"), FixedId("PPR-2"), "Anon_Anon"), Ident(FixedLabel("PPR"), FixedId("PPR-2"), "Anon_Anon"))
#=
# === Attempting to use a macro to simplify the newEV() function ===
macro create(id,name)
label = "EV"
return :(println($id," = new",$label,"(\"",$id,"\", \"",$name,"\")"))
end
#create("EV_97234894","new test")
#=
This generates
EV_97234894 = newEV("EV_97234894", "new test") which is what I want
but returns a type nothing – is that why REPL doesn't execute the result?
#=
# ==============================================
As far as I understand (and I'm not sure what the printing does in your example), you want a macro that expands
#create <id> <name>
to
<id> = newEV("<id>", name)
The following will achieve that:
julia> macro create(id::Symbol, name)
:($(esc(id)) = newEV($(String(id)), $name))
end
#create (macro with 1 method)
julia> #macroexpand #create EV_234324 "new test"
:(EV_234324 = (Main.newEV)("EV_234324", "new test"))
#macroexpand is for debugging, since I didn't copy your code. It simply gets the expression that results from a macro call.
escaping is necessary here, since you want the identifier given by the symbol id to end up being defined in the calling scope.
I'm trying to figure out how to have a quote block, when evaluated, return a symbol. See the example below.
function func(symbol::Symbol)
quote
z = $symbol
symbol
end
end
a = 1
eval(func(:a)) #this returns :symbol. I would like it to return :a
z
The symbol your function returned where the symbol function, due to the last symbol in your qoute did not have $ in front. The second problem is you would like to return the symbol it self, which requires you make a quote inside the quote similar to this question
Julia: How do I create a macro that returns its argument?
function func(s::Symbol)
quote
z = $s
$(Expr(:quote, s)) # This creates an expresion inside the quote
end
end
a = 1
eval(func(:a)) #this returns :a
z
I have this code which finds double quotation marks and converts the inside of those quotation marks into a string. It manages to find the first quotation mark but fails to find the second so: "this" would be "this . How do I get it I can get this function to find the full string.
Maybe this is too obvious:
if (ch = #"\"") then SOME(String(x ^ "\""))
I do not really understand your code: you return the string just after the first occurence of the quotation mark, but this string has been built with the characters that you've found before it. Moreover, why do you return SOME(Error) instead of NONE?
You need to use a boolean variable to know when the first quotation mark has been seen and to stop when the second one is found. So I would write something like this:
fun parseString x inStr quote =
case (TextIO.input1 inStr, quote) of
(NONE, _) => NONE
| (SOME #"\"", true) => SOME x
| (SOME #"\"", false) => parseString x inStr true
| (SOME ch, true) => parseString (x ^ (String.str ch)) inStr quote
| (SOME _ , false) => parseString x inStr quote;
and initialize quote with false.
I'm failing the last test case, which is the one with the spaces and single quotation mark.
I used s.strip, but the error still persists.
Is there another way to go about this?
Thank you.
from test import testEqual
def removeWhite(s):
s.strip()
s.strip("'")
return s
def isPal(s):
if s == "" or len(s) == 1:
return True
if removeWhite(s[0]) != removeWhite(s[-1]):
return False
return isPal(removeWhite(s[1:-1]))
testEqual(isPal(removeWhite("x")),True)
testEqual(isPal(removeWhite("radar")),True)
testEqual(isPal(removeWhite("hello")),False)
testEqual(isPal(removeWhite("")),True)
testEqual(isPal(removeWhite("hannah")),True)
testEqual(isPal(removeWhite("madam i'm adam")),True)
At first your removeWhite function doesn't return all spaces because strip only removes from the end and the beginning of a string. See:
>>> " a ".strip()
'a'
>>> " a a ".strip()
'a a'
So i suggest this approach:
def removeWhite(s):
return ''.join(filter(lambda x: x not in " '", s))
Please note that I use join because filter returns an iterator which needs to be converted back to a string.
For finding the palindromes i would suggest this function:
def isPal(s):
if len(s) <= 1: # Special case to prevent KeyError later
return True
stripped = removeWhite(s) # Strip off all whitespaces
first = stripped[:len(stripped) // 2] # First half of the string
if len(stripped) % 2: # Length of string is even?
second = stripped[len(stripped) // 2 + 1:] # Drop the middle character
else:
second = stripped[len(stripped) // 2:] # Else keep it
secondrev = ''.join(reversed(second)) # Reverse the second half
return first == secondrev # And return wether they're equal.
This holds for all your examples. But it think your isPal function should work too if you fix your removeWhite function