答案 0 :(得分:10)
答案 1 :(得分:8)
zipper 是一个纯函数数据结构,带有指向该结构的指针。换句话说,它是一个在某种结构中具有上下文的元素。
例如,Scalaz库提供了一个Zipper
类,用于对列表中特定元素的列表进行建模。
您可以获取列表的拉链,专注于第一个元素。
import scalaz._
import Scalaz._
val z: Option[Zipper[Int]] = List(1,2,3,4).toZipper
您可以使用Zipper
上的方法移动拉链的焦点,例如,您可以移动到当前焦点的下一个偏移。
val z2: Option[Zipper[Int]] = z >>= (_.next)
这就像List.tail
,但它会记住它的位置。
然后,一旦您选择了所选元素,就可以修改焦点周围的元素。
val swappedWithNext: Option[Zipper[Int]] =
for (x <- z2;
y <- x.delete)
yield y.insertLeft(x.focus)
注意:这是使用最新的Scalaz主干头,其中修复了Zipper的尾递归find
和move
方法的错误。
您想要的方法就是:
def swapWithNext[T](l: List[T], p: T => Boolean) : List[T] = (for {
z <- l.toZipper
y <- z.findZ(p)
x <- y.delete
} yield x.insertLeft(y.focus).toStream.toList) getOrElse l
这匹配基于谓词p
的元素。但你可以进一步考虑所有附近的元素。例如,要实现插入排序。
答案 2 :(得分:5)
答案 3 :(得分:1)
答案 4 :(得分:0)
怎么样:
public static void expand(final View v) {
v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final int targetHeight = v.getMeasuredHeight();
if ( v.getHeight() != targetHeight ) {
// Older versions of android (pre API 21) cancel animations for views with a height of 0 so use 1 instead.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? ViewGroup.LayoutParams.WRAP_CONTENT
: (int) (targetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setInterpolator(EasingsConstants.easeInOutQuart);
a.setDuration(computeDurationFromHeight(v));
v.startAnimation(a);
} else {
Log.d("AnimationUtil", "expand Already expanded ");
}
}
/**
* 1dp/ms * multiplier
*/
private static int computeDurationFromHeight(View v) {
return (int) (v.getMeasuredHeight() / v.getContext().getResources().getDisplayMetrics().density) * DURATION_MULTIPLIER;
}
对于dropIndex函数
,感谢http://www.scala-lang.org/old/node/5286