У меня есть следующая проблема в scala. Я должен найти первый элемент в списке al, который удовлетворяет функцию предиката двумя условиями в ИЛИ. Проблема состоит в том, что я хотел бы получить элемент, но также и знать, какое из этих двух условий было удовлетворено. Вот простой пример:
val l1 = List("A", "B", "AA", "BB")
val l2 = List("AA", "BB", "A", "B")
def c1(s: String) = s.startsWith("B")
def c2(s: String) = s.length == 2
println(l1.find(s => c1(s) || c2(s)))
println(l2.find(s => c1(s) || c2(s)))
результат:
Some(B)
Some(AA)
Для l1 случая я хотел бы иметь некоторое возвращаемое значение (Строка, например) указание, что c1 был удовлетворен (c2 для l2 случая). Возможное решение могло состоять в том, чтобы определить var перед тестом и установить его в c1 и функциях c2, но я хотел бы найти больше "функционального стиля" решением, возможно, что-то, что возвращает Кортеж как: (найденный элемент, удовлетворенное условие).
Заранее спасибо за справку
Я бы сделал это:
SCALA 2.8:
def find2p[T](l: List[T], p1: T => Boolean, p2: T => Boolean) =
l.view.map(el => (el, p1(el), p2(el))).find(t => t._2 || t._3)
SCALA 2.7:
def find2p[T](l: List[T], p1: T => Boolean, p2: T => Boolean) =
l.projection.map(el => (el, p1(el), p2(el))).find(t => t._2 || t._3)
Проекция
/ Проекция
гарантирует, что сопоставление будет выполнено по требованию по требованию вместо того, чтобы применяться ко всем списку.
Я не уверен, почему Eclipse не использует прокси для загрузки DTD. Это звучит как ошибка, и вы должны открыть дефект (если он не существует).
В качестве временного обхода можно добавить указанный пользователем вклад в каталог в Eclipse. Сначала загрузите DTD в локальную папку. Затем по пути Настройки - > XML- > Каталог XML выберите Пользовательские записи и нажмите кнопку Добавить и добавить файлы.
-121--4817712-Начиная с версии 2.8 команда file имеет аргумент копирования:
file(COPY yourDir DESTINATION yourDestination)
Обратите внимание, что:
-121--1002423-Относительные входные пути вычисляются относительно текущего источника и относительный адрес назначения оценивается относительно текущий каталог построения
Вот вариант ответа Даниэля (и ретронима).
Если вы просто хотите, чтобы предикат (из списка) был успешным, то вы можете использовать
def findP[T](list: Iterable[T], preds: Iterable[T=>Boolean]) = {
list.view.map( x => (x , preds.find( _(x) )) ).find( _._2.isDefined )
}
В качестве альтернативы, вы могли бы использовать список именованных предикатов:
def findP[T](list: Iterable[T],preds: Iterable[(T=>Boolean,String)]) = {
list.view.map(x => (x , preds.find( _._1(x) ))).find( _._2.isDefined )
}
scala> findP(
| List(1,2,3,4,5,6),
| List( ((i:Int)=>i>4,"Fred") , ((i:Int)=>(i%6)==0,"Barney"))
| )
res2: Option[(Int, Option[((Int) => Boolean, String)])] =
Some((5,Some((<function1>,Fred))))
Результат немного загроможден, но может быть развернут достаточно легко, чтобы дать именно то, что вы просили:
def findP[T](list: Iterable[T],preds: Iterable[(T=>Boolean,String)]) = {
list.view.map(x => (x , preds.find( _._1(x) ))).find( _._2.isDefined ) match {
case Some((i,Some((_,s)))) => Some((i,s))
case _ => None
}
}
(Это код для 2.8; переключить «вид» на «проекцию» для 2.7.)
def find[T](l1 : List[T], c1 : T => Boolean, c2 : T => Boolean) = ((None : Option[(String, T)]) /: l1)( (l, n) => l match {
case x : Some[_] => l
case x if c1(n) => Some("c1", n)
case x if c2(n) => Some("c2", n)
case _ => None
})
scala> find(l1, c1, c2)
res2: Option[(String, java.lang.String)] = Some((c1,B))
scala> find(l2, c1, c2)
res3: Option[(String, java.lang.String)] = Some((c2,AA))
В зависимости от ваших требований вы можете иметь параметр Map[T => Boolean, String] для возврата строк этикетки: def find[T](l1 : List[T], fs : Map[T => Boolean, String])
или определить свои собственные операторы.
В результате будет вычислен весь список, в котором найдены прерывания для первого найденного элемента.