所以我在Scala中有一个字符串数组,称为发音数组,如下所示:
["EH1","N", "D", "P", "ER0", "EH1", "N", "TH", "AH0", "S", "IY2", "Z"]
并且我想编写一条if else语句,该语句以相反的方式读取数组,并且一旦找到其中包含数字的字符串,它就会删除之后的所有字符串,或者将之前的所有内容放入一个单独的数组中。 / p>
因此,对于上面的示例,id希望其在“ IY2”处停止,然后仅使用[“ IY2”,“ Z”]创建一个新数组,或者删除之后的每个字符串并保留原始数组,例如I说,[“ IY2”,“ Z”]。数字本身不是整数btw,它是字符串的一部分,数字范围为0-2。
我已经尝试过使用if来查找数字0、1、2的反向循环,但是它返回每个带有数字的字符串,因此它返回[IY2,AH0,EH1,ER0,EH1],但没有找到第一个带数字的字符串后立即停止。而且,即使我找到了停止它的方法,我也不知道如何将字符串之前的所有内容放入新数组中。
for (sounds <- pronunciationArray.reverse) {
val number0 = sounds.contains("0")
if (number0 == true) {
println(sounds)
} else if (number0 == true){
println(sounds)
} else if (number1 == true){
println(sounds)
} else {
-1
}
}
我希望它只返回[“ IY2”,“ Z”],但它返回[IY2,AH0,EH1,ER0,EH1]
答案 0 :(得分:1)
我对您的目标尚不完全清楚,但是...
match t.x with
| None -> failwith "invariant for foo violated in bar”
| Some x -> (* carry on *)
...
(* don’t do this *)
type 'a one_or_two = 'a option * 'a option
...
let (first, second) = ... : _ one_or_two in
match first with
| None ->
(* now we know second must be Some *)
let second = extract_x second in
...
(* do this instead *)
type 'a one_or_two = First of 'a | Second of 'a | Both of 'a * 'a
有一个Array
函数可根据条件将其分为两部分-第一部分是数组的前缀,其中所有内容满足条件,第二部分是剩余部分。
比方说,您的条件是字符串包含span
而不是数字(只是因为我很懒-它可以是任何函数2
)。如果我们反转数组,然后对函数的 negation 进行拆分,则会得到:
f: String => Boolean
我们知道第二个数组的第一个元素满足我们的条件,因此我们可以组装结果:
scala> a.reverse.span(!_.contains("2"))
res5: (Array[String], Array[String]) = (Array(Z),Array(IY2, S, AH0, TH, N, EH1, ER0, P, D, N, EH1))
所有倒车也许不是最有效的,但可以完成工作。
答案 1 :(得分:1)
可以解决的一种算法是
示例
val pronunciationArray = Array("EH1","N", "D", "P", "ER0", "EH1", "N", "TH", "AH0", "S", "IY2", "Z")
def takeUntil(inputArray: Array[String], condition: String => Boolean): Array[String] = {
val findIndexFromLast = inputArray.reverse.zipWithIndex.collectFirst {
case (elem, index) if condition.apply(elem) => index
}
findIndexFromLast match { // pattern match to check if there exists element with 0, 1, or 2
case Some(indexFromLast) =>
inputArray.splitAt(inputArray.length - indexFromLast) match {
case (head, tail) => head.last +: tail
}
case None => // no element with 0, 1, 2 exists
inputArray
}
}
takeUntil(
inputArray = pronunciationArray,
condition = elem => elem.contains("0") || elem.contains("1") || elem.contains("2")) //gives [IY2, Z]
使用.span(predicate)
解决问题的另一种方法是.splitAt(index)
的更好版本
def takeUntil2(inputArray: Array[String]): Array[String] = {
inputArray.reverse.span {
element =>
!element.contains("0") && !element.contains("1") && !element.contains("2")
} match {
case (head, tail) => tail.take(1) ++ head.reverse
}
}
val result = takeUntil2(inputArray = pronunciationArray)
现在,使用scala方法,您可以扩展Array
以具有自定义功能,
implicit class ArrayOps(array: Array[String]) {
def takeUntil(predicate: String => Boolean): Array[String] = {
val splitAt = array.reverse.span(predicate.apply)
splitAt._2.take(1) ++ splitAt._1.reverse
}
}
val res = pronunciationArray
.takeUntil(predicate = elem => !elem.contains("0") && !elem.contains("1") && !elem.contains("2"))
答案 2 :(得分:0)
Scala数组提供了一个lastIndexWhere方法,该方法采用一个谓词,并返回满足该谓词的最后一个元素的索引:
val arr = Array("EH1","N", "D", "P", "ER0", "EH1", "N", "TH", "AH0", "S", "IY2", "Z")
val idx = arr.lastIndexWhere(e => e.intersect(Array('0', '1', '2')).size > 0)
然后调用takeRight方法以获得所需的结果
val res = arr.takeRight(arr.size - idx)