불변 목록에서 한 요소를 "제거"하는 관용적 스칼라 방식은 무엇입니까?
동일한 것으로 비교할 요소를 포함 할 수있는 목록이 있습니다. 비슷한 목록을 원하지만 하나의 요소가 제거되었습니다. 따라서 (A, B, C, B, D)에서 하나의 B 만 "제거"하여 예를 들어 (A, C, B, D)를 얻을 수 있기를 바랍니다. 결과의 요소 순서는 중요하지 않습니다.
저는 Scala에서 Lisp에서 영감을받은 방식으로 작성된 작업 코드를 가지고 있습니다. 이것을 수행하는 더 관용적 인 방법이 있습니까?
컨텍스트는 표준 카드 두 덱이 사용되는 카드 게임이므로 중복 카드가있을 수 있지만 여전히 한 번에 하나씩 플레이됩니다.
def removeOne(c: Card, left: List[Card], right: List[Card]): List[Card] = {
if (Nil == right) {
return left
}
if (c == right.head) {
return left ::: right.tail
}
return removeOne(c, right.head :: left, right.tail)
}
def removeCard(c: Card, cards: List[Card]): List[Card] = {
return removeOne(c, Nil, cards)
}
위의 답변에서 이러한 가능성을 보지 못 했으므로 다음과 같습니다.
scala> def remove(num: Int, list: List[Int]) = list diff List(num)
remove: (num: Int,list: List[Int])List[Int]
scala> remove(2,List(1,2,3,4,5))
res2: List[Int] = List(1, 3, 4, 5)
편집하다:
scala> remove(2,List(2,2,2))
res0: List[Int] = List(2, 2)
매력처럼 :-).
filterNot
방법을 사용할 수 있습니다 .
val data = "test"
list = List("this", "is", "a", "test")
list.filterNot(elm => elm == data)
이것을 시도해 볼 수 있습니다.
scala> val (left,right) = List(1,2,3,2,4).span(_ != 2)
left: List[Int] = List(1)
right: List[Int] = List(2, 3, 2, 4)
scala> left ::: right.tail
res7: List[Int] = List(1, 3, 2, 4)
그리고 방법으로 :
def removeInt(i: Int, li: List[Int]) = {
val (left, right) = li.span(_ != i)
left ::: right.drop(1)
}
불행히도 컬렉션 계층 구조는 -
on 에서 약간 엉망이 되었습니다 List
. 원하는 ArrayBuffer
대로 작동합니다.
scala> collection.mutable.ArrayBuffer(1,2,3,2,4) - 2
res0: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 2, 4)
그러나 슬프게도 List
결국 filterNot
스타일 구현으로 끝났고 따라서 "잘못된 일"을 수행 하고 사용자 에게 사용 중단 경고를 표시합니다 (실제로는 충분히 이해하기 filterNot
쉽습니다).
scala> List(1,2,3,2,4) - 2
warning: there were deprecation warnings; re-run with -deprecation for details
res1: List[Int] = List(1, 3, 4)
따라서 가장 쉬운 방법 List
은이 작업을 올바르게 수행하는 컬렉션으로 변환 한 다음 다시 변환하는 것입니다.
import collection.mutable.ArrayBuffer._
scala> ((ArrayBuffer() ++ List(1,2,3,2,4)) - 2).toList
res2: List[Int] = List(1, 3, 2, 4)
또는 가지고있는 코드의 논리를 유지하면서 스타일을보다 관용적으로 만들 수 있습니다.
def removeInt(i: Int, li: List[Int]) = {
def removeOne(i: Int, left: List[Int], right: List[Int]): List[Int] = right match {
case r :: rest =>
if (r == i) left.reverse ::: rest
else removeOne(i, r :: left, rest)
case Nil => left.reverse
}
removeOne(i, Nil, li)
}
scala> removeInt(2, List(1,2,3,2,4))
res3: List[Int] = List(1, 3, 2, 4)
def removeAtIdx[T](idx: Int, listToRemoveFrom: List[T]): List[T] = {
assert(listToRemoveFrom.length > idx && idx >= 0)
val (left, _ :: right) = listToRemoveFrom.splitAt(idx)
left ++ right
}
// throws a MatchError exception if i isn't found in li
def remove[A](i:A, li:List[A]) = {
val (head,_::tail) = li.span(i != _)
head ::: tail
}
가능한 한 가지 해결책으로 첫 번째 적합한 요소의 색인을 찾은 다음이 색인에서 요소를 제거 할 수 있습니다.
def removeOne(l: List[Card], c: Card) = l indexOf c match {
case -1 => l
case n => (l take n) ++ (l drop (n + 1))
}
어때
def removeCard(c: Card, cards: List[Card]) = {
val (head, tail) = cards span {c!=}
head :::
(tail match {
case x :: xs => xs
case Nil => Nil
})
}
이 보이면 return
문제가있는 것입니다.
Just another thought on how to do this using a fold:
def remove[A](item : A, lst : List[A]) : List[A] = {
lst.:\[List[A]](Nil)((lst, lstItem) =>
if (lstItem == item) lst else lstItem::lst )
}
Generic Tail Recursion Solution:
def removeElement[T](list: List[T], ele: T): List[T] = {
@tailrec
def removeElementHelper(list: List[T],
accumList: List[T] = List[T]()): List[T] = {
if (list.length == 1) {
if (list.head == ele) accumList.reverse
else accumList.reverse ::: list
} else {
list match {
case head :: tail if (head != ele) =>
removeElementHelper(tail, head :: accumList)
case head :: tail if (head == ele) => (accumList.reverse ::: tail)
case _ => accumList
}
}
}
removeElementHelper(list)
}
val list : Array[Int] = Array(6, 5, 3, 1, 8, 7, 2)
val test2 = list.splitAt(list.length / 2)._2
val res = test2.patch(1, Nil, 1)
object HelloWorld {
def main(args: Array[String]) {
var months: List[String] = List("December","November","October","September","August", "July","June","May","April","March","February","January")
println("Deleting the reverse list one by one")
var i = 0
while (i < (months.length)){
println("Deleting "+months.apply(i))
months = (months.drop(1))
}
println(months)
}
}
'Development Tip' 카테고리의 다른 글
핀을 건드리지 않고 MKAnnotationView의 콜 아웃 뷰를 트리거하는 방법은 무엇입니까? (0) | 2020.10.20 |
---|---|
인덱스 배열 위치가 0이 아닌 다른 일반적인 "c 유사"또는 비 "c 유사"언어가 있습니까? (0) | 2020.10.20 |
두 번째 원격 호스트로 scp하는 방법 (0) | 2020.10.20 |
PGError : ERROR : 관계에 대한 권한이 거부되었습니다 (Heroku 사용시). (0) | 2020.10.20 |
Git : 수동으로 삭제 한 파일을 커밋하는 방법? (0) | 2020.10.20 |