2016-01-23 4 views
0

Я этот метод:Scala: Как использовать foldLeft с общим массивом?

def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = { 
    val sorted = for (it <- as.sliding(2)) 
     yield { 
     if (it.length == 2) ordered.apply(it(0), it(1)) 
     else true 
     } 

    sorted.find(!_).isEmpty 
} 

То, что я хотел бы сделать, это использовать foldLeft и применить бинарный оператор. Однако foldLeft требует начального значения, и я не знаю, какое исходное значение я могу предоставить, не зная реального типа A.

+0

Взгляните на это: http://stackoverflow.com/a/7852918/1153435 – Eduardo

+0

@Eduardo уже сделал. В этой теме нет консенсуса о том, что делать для взлома. Некоторые говорят, что «ломать» - лучшая вещь в Скале, так как нарезанный хлеб, другие считают, что это зло, поскольку оно выдает исключение под капотом. –

+0

Вы пробовали 'reduceLeft'? – Jus12

ответ

1

Я думаю, что то, что вы делаете, может быть упрощено.

def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = { 
    if (as.size < 2) 
    true 
    else 
    as.sliding(2).find(x => !ordered(x(0),x(1))).isEmpty 
} 

isSorted: [A](as: Array[A], ordered: (A, A) => Boolean)Boolean 

scala> isSorted(Array(2), {(a:Int,b:Int) => a < b}) 
res42: Boolean = true 

scala> isSorted(Array(2,4), {(a:Int,b:Int) => a < b}) 
res43: Boolean = true 

scala> isSorted(Array(2,4,5), {(a:Int,b:Int) => a < b}) 
res44: Boolean = true 

scala> isSorted(Array(2,14,5), {(a:Int,b:Int) => a < b}) 
res45: Boolean = false 

Или, возможно, немного более сжато (но не обязательно легче понять):

def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = { 
    if (as.size < 2) 
    true 
    else 
    !as.sliding(2).exists(x => ordered(x(1),x(0))) 
} 

UPDATE

Хорошо, я думаю, что я получил лаконичный приз прибили.

def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = 
    as.isEmpty || as.init.corresponds(as.tail)(ordered) 
+0

Говоря о лаконичности и лени, и заимствуя вашу идею, я мог бы сделать - '(as.isEmpty) || as.view.sliding (2) .find (it =>! ordered (it (0), it (1))). isEmpty' –

+0

Да, хотя тест 'isEmpty' пропустит одноэлементный массив. – jwvh

+0

Ух, да, я хотел использовать 'as.size <2', но почему-то закончил с' isEmpty'. –

1

Для начального значения для foldLeft вы можете использовать головку вашего входного массива. Однако foldLeft не хороший выбор, чтобы проверить, если массив отсортирован, так как вы должны завершить метод, когда первый несортированный элемент найден, но foldLeft будет проходить весь массив

Edit:

Я хотел бы использовать сочетание молнии с хвост и существует:

isSorted(...) = 
    if (as.isEmpty) true 
    else !as.zip(as.tail).exists { case (a,b) => !ordered(a,b)} 
+0

Я не могу использовать головку, если массив пуст. Если я должен ввести «if-else», я пишу больше кода. Что касается обхода, что вы предлагаете использовать? –

+0

У вас уже есть if-else для случая, когда массив пуст – Nyavro

+0

И я ищу более сжатое решение, следовательно, вопрос. –

1

Добавления к другим ответам, вы, вероятно, не хотите, чтобы перебрать весь массив, а скорее прекратить в тот момент, вы найдете неупорядоченную пару. Итак, как насчет этого?

def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = { 
    var sorted = true 
    val ita = as.sliding(2) 
    while (sorted && ita.hasNext) { 
    val it = ita.next 
    sorted = if (it.size > 1) ordered(it(0), it(1)) else true 
    } 
    sorted 
} 

val a = Array(1, 3, 2, 4, 5) 
val b = Array(1, 2, 3, 4, 5) 

isSorted[Int](a, _ < _) // returns false 
isSorted[Int](b, _ < _) // returns true 
Смежные вопросы