简体   繁体   English

过滤列表列表中的元组[Haskell]

[英]Filter tuples in list of lists [Haskell]

I have a list of lists of tuples: 我有一个元组列表的列表:

let list = [[(1,(2,2)),(0,(3,2)),(0,(4,2))],[(0,(2,3)),(0,(3,3)),(0,(4,3))],[(0,(2,4)),(0,(3,4)),(0,(4,4))]]

I would like to filter them by the first value of each tuple. 我想通过每个元组的第一个值过滤它们。 That's what I tried... 那就是我尝试过的

compute :: Matrix -> Coordinates -> Matrix
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- list]

with

type Matrix = [[Int]]
type Coordinates = (Int, Int)

That's the error I got: 那就是我得到的错误:

ContiguousRegion.hs:20:36:
Couldn't match expected type ‘[Int]’
            with actual type ‘(Integer, (t0, t1))’
In the pattern: (a, (_, _))
In the first argument of ‘filter’, namely
  ‘(\ (a, (_, _)) -> a /= 1)’
In the expression:
  filter
    (\ (a, (_, _)) -> a /= 1) [row | row <- checkAround m (x, y)]

ContiguousRegion.hs:20:58:
Couldn't match type ‘(Int, (Int, Int))’ with ‘Int’
Expected type: [Int]
  Actual type: [(Int, (Int, Int))]
In the expression: row
In the second argument of ‘filter’, namely
  ‘[row | row <- checkAround m (x, y)]’
Failed, modules loaded: none.

How can I solve this? 我该如何解决? Thanks! 谢谢!

Let's take a few steps to simplify the compute function and figure out the problem: 让我们采取一些步骤来简化compute功能并找出问题所在:

  1. First of all, [row | row <- list] 首先, [row | row <- list] [row | row <- list] does nothing, it's equivalent to just list , so we can remove it and replace it with list , to make the function easier to read: [row | row <- list]不执行任何操作,仅等效于list ,因此我们可以将其删除并替换为list ,以使函数更易于阅读:

     compute m (x,y) = filter (\\(a,(_,_)) -> a /= 1) list 

    By the way, in your message I see that list isn't what the argument to filter is actually called. 顺便说一句,在您的消息中,我看到list实际上不是要过滤的参数。 Instead, it's a checkAround m (x, y) , so compute should probably look like this: 相反,它是一个checkAround m (x, y) ,因此compute可能看起来像这样:

     compute m (x,y) = filter (\\(a,(_,_)) -> a /= 1) $ checkAround m (x, y) 
  2. The function you're passing to filter is unnecessarily complicated, we can replace it with \\(a,_) -> a /= 1 or even (/=1) . fst 您传递给filter的函数不必要地复杂,我们可以用\\(a,_) -> a /= 1甚至(/=1) . fst代替它(/=1) . fst (/=1) . fst to make it less noisy. (/=1) . fst使它减少噪音。 Doing that gives us: 这样做给我们:

     compute m (x,y) = filter ((/=1) . fst) list 
  3. I'd say it's now much easier to see the problem. 我想说现在更容易发现问题了。 Your list has the type [[(Int, (Int, Int))]] , ie. 您的list的类型为[[(Int, (Int, Int))]] ,即。 it's a list of lists of tuples. 这是元组列表的列表。

    But the predicate your passing into filter is expecting a tuple, therefore filter itself is expecting a list of tuples. 但是您进入filter的谓词期望一个元组,因此filter本身期望一个元组列表。

    This is an obvious type mismatch. 这是一个明显的类型不匹配。 How do we solve this? 我们该如何解决? I don't know, that's up to you, but I guess you want to filter the inner list. 我不知道,这取决于您,但是我想您想过滤内部列表。

    How do we do this? 我们如何做到这一点? Well, we need to go through each of the inner lists, filter them and put the filtered ones in a new list. 好吧,我们需要遍历每个内部列表,对其进行过滤,然后将过滤后的列表放入新列表中。 This is exactly what map (or fmap ) can help us with. 这正是map (或fmap )可以帮助我们的。 Let's map the filter we've constructed over list : 让我们将我们构建的过滤器映射到list

     compute m (x,y) = map (filter ((/=1) . fst)) list 
  4. Unfortunately, the above still gives us a type error: 不幸的是,以上仍然给我们一个类型错误:

     Couldn't match type '(Integer, (Integer, Integer))' with 'Int' Expected type: [[Int]] Actual type: [[(Integer, (Integer, Integer))]] 

    Well, why is that? 好吧,为什么呢? We know that the Actual type is the type of list and the type of the filtered list as well, but what is the Expected type and why is it a [[Int]] ? 我们知道, Actual typelist的类型,也是过滤后的列表的类型,但是Expected type是什么,为什么它是[[Int]]

    The answer lies in your type signature, Matrix -> Coordinates -> Matrix . 答案在于您的类型签名Matrix -> Coordinates -> Matrix compute is supposed to produce a list of lists of Int s, but we're filtering something a bit different. compute应该产生一个Int列表的列表,但是我们在过滤一些不同的东西。

At this point I don't really know what you'd like to do, so I'll just end here, but I suspect you either need to change compute 's type signature or you need to somehow merge m with the filtered results to create a new matrix. 在这一点上,我真的不知道您想做什么,所以我就在这里结束,但是我怀疑您要么需要更改compute的类型签名,要么需要以某种方式将m与过滤后的结果合并为创建一个新矩阵。

Is this what you are trying to do? 这是您要做什么?

type SparseMatrix = [Row]
type Row = [Element]
type Element = (Int, Coordinates)
type Coordinates = (Int, Int)

removeRowVal :: Row -> Int -> Row
removeRowVal row i = filter ((/= i).fst) row

removeSMVal :: SparseMatrix -> Int -> SparseMatrix
removeSMVal sm i = [removeRowVal row i | row <- sm]

Even if your list is not some kind of oddly structured sparse matrix representation, I think the final result is what you described. 即使您的list不是某种奇怪的稀疏矩阵表示形式,我也认为最终结果就是您所描述的。

Problem 1: Your definition of compute refers to list , but list is not a parameter. 问题1:您对compute定义是指list ,但是list不是参数。

Problem 2: If you change list to m your code is correct, but the type signature you gave is not correct. 问题2:如果将list更改为m代码是正确的,但是给出的类型签名不正确。

Solution: 解:

Change list to m , and don't give a type a signature: list更改为m ,并且不给类型签名:

compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- m]

Now ask ghci what the type signature should be: 现在问ghci类型签名应该是什么:

ghci> :t compute
compute
    :: (Eq a, Num a) => [(a, (t2, t3))] -> (t, t1) -> [(a, (t2, t3))]

Now you see that that type Matrix should be defined as 现在您将看到type Matrix应定义为

type Matrix = [ (Int, (Int,Int) ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM