怎样才能移动某些数组元素? [英] How would be a functional approach to shifting certain array elements?

查看:96
本文介绍了怎样才能移动某些数组元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有复选框的项目列表的Scala应用程序,所以用户选择一些,然后点击一个按钮将它们向上移动一个位置(左侧)。我决定编写一个函数来转换符合给定谓词的任意类型的元素。所以,如果你有这些元素:

  abc DE fgh I 

,谓词是大写字母,函数会返回这个:

  $ / code> 

简而言之,任何符合谓词的连续元素序列与它左侧的单个元素交换。



我提出了以下丑陋的命令式实现。我希望看到一个不错的,希望可读的功能性解决方案。

  def shiftUp [T](a:Array [T ],shiftable:T => Boolean)= {
val s = new Array [T](a.length)
var i = 0
var j = 0
while (a(i))&< a.length-1&&&&&&&&&&&&&可移动(a(i + 1) ))
{
var ii = i + 1
while(ii {
s(j)= a(ii)
ii = ii + 1
j = j + 1
}
s(j)= a(i)
i = ii
}
else
{
s(j)= a(i)
i = i + 1
}
j = j + 1 $ b $编辑:谢谢大家,我希望你已经喜欢练习!

解决方案

这是一个purel y功能实现

  def shiftElements [A](l:List [A],pred:A =>布尔):List [A] = {
def aux(lx:List [A],accum:List [A]):List [A] = {
lx match {
case Nil =>如果pred(b)&& amp;& amp;& !pred(a)=> aux(a :: xs,b :: accum)
case x :: xs => aux(xs,x :: accum)
}
}
aux(l,Nil).reverse
}

这里有一个使用可变性的内部变得更快

  import scala.collection.mutable.ListBuffer 
def shiftElements2 [A](l:List [A],pred:A => Boolean):List [A] = {
val buf = new ListBuffer [A]
def aux(lx:List [A]){
lx match {
case Nil => ()
case a :: b :: xs if pred(b)&& !pred(a)=> {
buf.append(b)
aux(a :: xs)
}
case x :: xs => {
buf.append(x)
aux(xs)
}
}
}
aux(l)
buf.toList
}


I have a Scala app with a list of items with checkboxes so the user select some, and click a button to shift them one position up (left). I decided to write a function to shift elements of some arbitrary type which meet a given predicate. So, if you have these elements:

a b c D E f g h I

and the predicate is "uppercase characters", the function would return this:

a b D E c f g I h

In short, any sequence of contiguous elements that meet the predicate are swapped with the single element at the left of it.

I came up with the following ugly imperative implementation. I would like to see a nice, and hopefully readable, functional solution.

def shiftUp[T](a:Array[T], shiftable: T => Boolean) = {
    val s = new Array[T](a.length)
    var i = 0
    var j = 0
    while(i < a.length)
    {
        if(!shiftable(a(i)) && i < a.length - 1 && shiftable(a(i+1)))
        {
            var ii = i + 1
            while(ii < a.length && shiftable(a(ii)))
            {
                s(j) = a(ii)
                ii = ii+1
                j = j+1
            }
            s(j) = a(i)
            i = ii
        }
        else
        {
            s(j) = a(i)
            i = i+1
        }
        j = j+1
    }
    s
}

EDIT: Thanks all, I hope you have enjoyed the exercise!

解决方案

Here's a purely functional implementation

def shiftElements[A](l: List[A], pred: A => Boolean): List[A] = {
  def aux(lx: List[A], accum: List[A]): List[A] = {
    lx match {
      case Nil => accum
      case a::b::xs if pred(b) && !pred(a) => aux(a::xs, b::accum)
      case x::xs => aux(xs, x::accum)
    }
  }
  aux(l, Nil).reverse
}

And here's one that uses mutability on the inside to be faster

import scala.collection.mutable.ListBuffer
def shiftElements2[A](l: List[A], pred: A => Boolean): List[A] = {
  val buf = new ListBuffer[A]
  def aux(lx: List[A]) {
    lx match {
      case Nil => ()
      case a::b::xs if pred(b) && !pred(a) => {
        buf.append(b)
        aux(a::xs)
      }
      case x::xs => {
        buf.append(x)
        aux(xs)
      }
    }
  }
  aux(l)
  buf.toList
}

这篇关于怎样才能移动某些数组元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆