Overview
trying to use a conditional statement with a list
how do you iterate in the list to only execute on the conditional statement when it has iterated to theItem only in that specific loop iteration.
Code:
It should say hello but it doesn't
set myList to {"Hello", "Goodbye", "I must be going"}
repeat with theItem in myList
log theItem
if theItem = "Hello" then
say theItem
end if
end repeat
but if I do this it works
set myList to {"Hello", "Goodbye", "I must be going"}
repeat with theItem in myList
log theItem
if theItem is in "Hello" then
say theItem
end if
end repeat
Is the only way to use a conditional statement is with "is in" to execute code in the conditional statement?
If your script only wants to check that "hello" is in your list, you do not need a loop:
set myList to {"Hello", "Goodbye", "I must be going"}
if "Hello" is in myList then
log "the list contains item 'hello'"
else
log "no item found"
end if
If you still want to use a loop, probably the main reason is that you want to know the item number (?).
set myList to { "Hello", "Goodbye", "I must be going"}
repeat with i from 1 to count of myList
set theItem to item i of myList
if theItem = "Hello" then exit repeat
end repeat
log "item " & i & " is my target !!"
Finally, to answer to your initial question, Applescript documentation states that if the "if" checks item of a list, it must be referred as 'contents of' (see :Apple Documentation about Repeat with)
Then script bellow is also working:
set myList to {"Hello", "Goodbye", "I must be going"}
repeat with theItem in myList
log theItem
if (contents of theItem) is "Hello" then
log "this is my item"
end if
end repeat
In the repeat with theItem in myList loop theItem is actually a reference to
AppleScript dereferences the object silently on your behalf except on an equality check.
In this particular case you have to deference the object explicitly with contents of
set myList to {"Hello", "Goodbye", "I must be going"}
repeat with theItem in myList
log theItem
if contents of theItem = "Hello" then
say theItem
end if
end repeat
This doesn't affect the repeat with i from 1 to (count myList) syntax because item i of myList derefernces the object implicitly.
if theItem as text = "Hello" then
TheItem refers to the item in the list. « Hello » is a text.
Related
Example: "? ? ?" -> "1 2 3"
Seems like it can't be done with Regex.replace:
Regex.replace ~r/\?/, "? ? ?", fn(token) -> ...some code here... end
because there's no way to have a mutable counter.
You are right, you can't have mutable counter in Regex replace, so you will have to recursively change question marks one by one. #JustMichael answer looks nice. If there can be something other than spaces between question marks, I would do it this way:
def number_question_marks(string), do: number_question_marks("", string, 1)
#helper takes previous and current string
#if nothing changes we end recursion
def number_question_marks(string, string, _), do: string
#if something changed we call recursively
def number_question_marks(_previous, string, counter) do
new = Regex.replace(~r/\?/, string, inspect(counter), global: false)
number_question_marks(string, new, counter + 1)
end
"? ? ?"
|> String.split(" ")
|> Enum.map_reduce(1, fn(x, acc) -> {acc, acc + 1} end)
|> elem(0)
|> Enum.join(" ")
It works but I guess there is a shorter way to do that.
I have a list of bigrams of a sentence and another original list of relevantbigrams, I want to check that if any of the relevantbigrams are present in the sentences then I want to return the sentence. I was thinking of implementing it as follows: map each of the bigrams in the list to the sentence they come from then do a search on the key an return the value.
example:
relevantbigrams = (This is, is not, not what)
bigrams List(list(This of, of no, no the),list(not what, what is))
So each list is a bigram of separate sentences. Here "not what" from the second sentence matches, so I would like to return the second sentence. I am planning to have a map of Map("This of" -> "This of no the", "of no" ->"This of no the", "not what"->"not what is"). etc. and return the sentences that match on relevant bigram, so here I return "not what is"
This is my code:
val bigram = usableTweets.map(x =>Tokenize(x).sliding(2).flatMap{case Vector(x,y) => List(x+" "+y)}.map(z => z, x))
for(i<- 0 to relevantbigram.length)
if(bigram.contains(relevantbigram(i)))) bigram.get(relevantbigram(i))
else useableTweets.head
You got the order or flatMap and map the wrong way around:
val bigramMap = usableTweets.flatMap { x =>
x.split(" ").sliding(2).
map(bg => bg.mkString(" ") -> x)
} toMap
Then you can do your search like this:
relevantbigrams collect { rb if theMap contains rb => bigramMap(rb) }
Or
val found =
for {
rb <- relevantbigrams
sentence <- theMap get rb
} yield sentence
Both should give you a list, but from your code it appears you want to default to the first sentence if your search found nothing:
found.headOption.getOrElse(usableTweets.head)
I have a doubt concerning the use of switch in tcl. Mainly, I was wondering if it was possible to make something like:
switch myvar {
list1 {
puts "myvar matches contents of list1"; }
list2 {
puts "myvar matches contents of list2"; }
default {
puts "myvar doesn't match any content of any list"; }
}
In here, list1 and list2 would be either a list or array of strings containing the names of different files.
Is this even possible without making a very detailed regexp search?
Thanks!
You can rewrite it as an if elseif else construct easily, as Brian Fenton already said (and simplify it with the 'in' operator too.
if {$myvar in $list1} {
puts "myvar matches content of list"
} elseif {$myvar in $list2} {
puts "myvar matches content of list2"
} elseif {
puts "myvar doesn't match any content of any list"
}
You could of course wrap up the code and write your own switch version that does what you want, after all, this is Tcl...
proc listswitch {item conditions} {
if {[llength $conditions] % 2} {
return -code error "Conditions must be pairs"
}
set code ""
foreach {cond block} $conditions {
if {$cond eq "default"} {
set code $block
break
} elseif {$item in $cond} {
set code $block
break
}
}
if {$code ne ""} {
uplevel 1 $code
}
}
listswitch 10 {
{10 20 30 50} {
puts "Match in list 1" }
{50 20 90 11} {
puts "Match in list 2"
}
default {
puts "No match"
}
}
You need to worry a little if you want to match filenames literally, or what kind of equality your interested in though. There are some subtle things there, like case insensitive filesystems, different directory separators, absolute vs. relative and even stuff like filesystem encodings which might change the outcome.
Nice question Jason. At first, I thought you wanted a way to compare the contents of two lists. But I think you want to check if the string is a member of the lists. I don't see any easy way to do that with switch, so what I would do is very simply to use lsearch.
if {[lsearch $list1 $myvar ] != -1} {
puts "myvar matches contents of list1"; }
} elseif {[lsearch $list2 $myvar ] != -1} {
puts "myvar matches contents of list2"; }
} else
puts "myvar doesn't match any content of any list"; }
}
Say I have a TCL list, and I have append some elements to my list. Now I want to check if I have appended 6 or 7 elements.
In order to check if list element exists in the place specified by an index I have used:
if { [info exists [lindex $myList 6]] } {
#if I am here then I have appended 7 elems, otherwise it should be at least 6
}
But seams this does not work. How I should do that? properly? It is OK to check if { [lindex $myList 6]] eq "" }
I found this question because I wanted to check if a list contains a specific item, rather than just checking the list's length.
To see if an element exists within a list, use the lsearch function:
if {[lsearch -exact $myList 4] >= 0} {
puts "Found 4 in myList!"
}
The lsearch function returns the index of the first found element or -1 if the given element wasn't found. Through the -exact, -glob (which is the default) or -regexp options, the type of pattern search can be specified.
Why don't you use llength to check the length of your list:
if {[llength $myList] == 6} {
# do something
}
Of course, if you want to check the element at a specific index, then then use lindex to retrieve that element and check that. e.g. if {[lindex $myList 6] == "something"}
Your code using the info exists is not working, because the info exists command checks if a variable exists. So you are basically checking if there is a variable whose name equals the value returned by [lindex $myList 6].
Another way to check for existence in a list in TCL is to simply use 'in', for instance:
if {"4" in $myList} {
puts "Found 4 in my list"
}
It's slightly cleaner/more readable!
VIM: Does anyone know how to put a string from an input dialog in a list?
p.e.:
the string "3,5,12,15"
to:
list item[1] = 3
list item[2] = 5
list item[3] = 12
etc.
and how can I know how many list items there are?
From :h E714
:let l = len(list) " number of items in list
:let list = split("a b c") " create list from items in a string
In your case,
let string = "3,5,7,19"
let list = split(string, ",")
echo len(list)
Use split, len and empty functions:
let list=split(string, ',')
let list_length=len(list)
" If all you want is to check whether list is empty:
if empty(list)
throw "You must provide at least one value"
endif
Note that if you want to get a list of numbers out of the string, you will have to use map to transform list elements into numbers:
let list=map(split(string, ','), '+v:val')
Most of time you can expect strings be transformed into numbers, but sometimes such transformation is not done.