我创建了以下数据类型。
Array_
现在,我想创建一个更新函数 - 给定索引,update :: ( Int, Array_ a, a ) -> Array_ a
和新值 - 更新给定索引处的数组值。
这是函数的签名......
update :: ( Int, Array_ a, a ) -> Array_ a
update( i, A[], new_value ) = error( ( show i ) ++ " is not an index" )
update( i, A( ( j, Just_ x ):l ), new_value )
| i == j = A( ( j, Just_ new_value ):l )
| i /= j = update ( i, A l, new_value )
......这是完整的功能
++
问题出现在函数的最后一行。 这是对列表末尾的递归调用,但它不保留以前考虑的数组元素。
我正考虑使用:
运算符或... i /= j = ( j, Just_ x ):update ( i, A l, new_value )
运算符,但两次都出错。
... i /= j = A[( j, Just_ x )] ++ update ( i, A l, new_value )
var arr1 = [CustomObject]()
var arr2 = [CustomObject]()
var arr3 = [CustomObject]()
var arr4 = [CustomObject]()
self.arr3 = self.arr1 + self.arr2 //concatenate two arrays
self.arr4 = Array(Set(arr3)) // find out uniq values
// below is the extension
extension Array where Element : Hashable {
var unique: [Element] {
var uniqueValues: [Element] = []
forEach { item in
if !uniqueValues.contains(item) {
uniqueValues += [item]
}
}
return uniqueValues
}
}
我该如何区别对待?
答案 0 :(得分:3)
首先,它有点 un-Haskell 与元组一起使用,通常你定义单独的参数,如:
update :: Int -> Array_ a -> a -> Array_ a
这样您就可以轻松使用update 5
函数,稍后您将提供其他参数。
然而问题在于你的最后一个分支:
| i /= j = update i (A l) new_value
因此执行递归调用,但递归调用的结果将是 final 结果。为了解决此问题,您只需添加您检查的项目,并且与索引不匹配。由于您对所有索引失败执行此操作,因此所有不匹配的索引将位于最终结果中,因此:
| i /= j = (j, Just_ x) : update i (A l) new_value.
现在我们获得:
update :: Int -> Array_ a -> a -> Array_ a
update i (A []) new_value = error( ( show i ) ++ " is not an index" )
update i (A ((j, Just_ x):l)) new_value
| i == j = A ((j, Just_ new_value):l)
| i /= j = let A t = update i (A l) new_value in A ((j, Just_ x):t)
话虽如此,我们仍然可以采取一些措施来改善我们的职能:
@
来阻止我们重新打包列表的头部。==
和/=
,编译器可能会出错。最好使用otherwise
(最后一个分支中的True
别名(这与Java中的else
或多或少相同)。hlint
获得一些额外的美化。如果我们考虑上述评论,我认为 - 更优雅的功能将是:
update :: Int -> Array_ a -> a -> Array_ a
update i (A []) _ = error $ show i ++ " is not an index"
update i (A (h@(j,Just_):l)) new_value
| i == j = A ((j, Just_ new_value):l)
| otherwise = let A t = update i (A l) new_value in A (h:t)
最后还有一个案例尚未解决:如果列表中有Nothing_
,该怎么办?如果您不关心该值是Just_ x
还是Nothing_
,则可以将其重写为:
update :: Int -> Array_ a -> a -> Array_ a
update i (A []) _ = error $ show i ++ " is not an index"
update i (A (h@(j,_):l)) new_value
| i == j = A ((j, Just_ new_value):l)
| otherwise = let A t = update i (A l) new_value in A (h:t)