简体   繁体   English

从列表元组列表中过滤元组

[英]Filter Tuples from List of List Tuples

I have a tuple nested inside of two lists and I'm trying to filter the tuples depending if they're consistent or not.我有一个嵌套在两个列表中的元组,我试图根据它们是否一致来过滤这些元组。

I need to check the first element of the tuples and any that match should have the same Bool.我需要检查元组的第一个元素,并且任何匹配的元素都应该具有相同的 Bool。 Otherwise it should be removed from the List.否则它应该从列表中删除。 My input looks something like this.我的输入看起来像这样。

[[('a',True),('a',False),('b',True),('c',False),('a',False)], [('a',True),('a',True),('b',True),('b',False)]]

and I'm trying to achieve:我正在努力实现:

[[('b',True),('c',False),], [('a',True),('a',True)]]

'a's where removed from the first List as both True and False was tied to 'a', then the 'b's were removed from the second List as again both True and False was tied to 'b'. 'a' 从第一个列表中删除,因为 True 和 False 都与 'a' 相关联,然后 'b' 从第二个列表中删除,因为 True 和 False 都与 'b' 相关联。

I thought by breaking the task up into seperate functions it would make it easier.我认为通过将任务分解为单独的功能,它会更容易。 So I created this mapTuples functions to create a list of tuples that have the same first element.所以我创建了这个 mapTuples 函数来创建一个具有相同第一个元素的元组列表。

mapTuples :: [(Char,Bool)] -> [(Char,Bool)]
mapTuples (x:y:ys) | fst(x) == fst(y) = ((y):mapTuples (x:ys))
                   | otherwise = mapTuples (x:ys)
mapTuples (x:[]) = [x]
mapTuples [] = []

From here I've made a function checkTuples, to check the Lists from the above function and see if any of the Bool's don't match.从这里我制作了一个 function checkTuples,以检查上述 function 中的列表,看看是否有任何布尔值不匹配。 It'll return True if they all match or False if they don't.如果它们都匹配,它将返回 True,否则返回 False。

checkTuples :: [(Char,Bool)] -> Bool
checkTuples (x:y:ys) | snd(x) /= snd(y) = False
                     | otherwise = checkTuples(x:ys)
checkTuples (x:[]) = True

Then finally I have my removeConflicts to remove any of the inconsistent Tuples.最后我有我的 removeConflicts 来删除任何不一致的元组。 Which I'm using to loop through my Lists and Tuples.我用它来循环我的列表和元组。

removeConflicts :: [[(Char,Bool)]] -> [[(Char,Bool)]]
removeConflicts (x:ys) | checkTuples(mapTuples(x)) == False = removeConflicts(ys)
                       | otherwise = x:removeConflicts(ys)
removeConflicts [] = []

Which currently doesn't work as intended and I know its because of this part:目前无法按预期工作,我知道这是因为这部分:

False = removeConflicts(ys)

I believe I need to somehow also include my x value that has been filtered.我相信我还需要以某种方式包括已过滤的 x 值。 But I'm not sure how to go about doing so.但我不确定如何 go 这样做。 Something like就像是

removeConflicts (x:ys) | checkTuples(mapTuples(x)) == False = removeConflicts(filtered(x):ys)

Where filtered(x) removes unwanted Tuples.在哪里过滤(x)删除不需要的元组。

Hope this all makes sense and sorry for long winded explanation, didn't want to leave anything out.希望这一切都有意义,并对冗长的解释感到抱歉,不想遗漏任何内容。

My first remark is that you've complicated this specification by talking about lists of lists of tuples.我的第一句话是,您通过谈论元组列表的列表使本规范变得复杂。 The computation you describe is to transform each list within this nested list in the same way: that's what map does.您描述的计算是以相同的方式转换此嵌套列表中的每个列表:这就是map所做的。 So we can reduce the problem already to所以我们可以将问题减少到

removeConflicts :: [[(Char, Bool)]] -> [[(Char, Bool)]]
removeConflicts = map processList

for some processList:: [(Char, Bool)] -> [(Char, Bool)] we must define.对于某些processList:: [(Char, Bool)] -> [(Char, Bool)]我们必须定义。 Let's start on that.让我们开始吧。

processList :: [(Char, Bool)] -> [(Char, Bool)]
processList [] = []
processList ((label, value):more) = _

Easy enough to process an empty list.很容易处理一个空列表。 For a non-empty list, we want to split the list into two parts: the tuples that share the same label as this, and the tuples that don't.对于非空列表,我们希望将列表分成两部分:与此共享相同 label 的元组和不共享的元组。 Some Hoogling around will reveal partition is suited to this task, so:一些 Hoogling 会发现partition适合这个任务,所以:

processList :: [(Char, Bool)] -> [(Char, Bool)]
processList [] = []
processList xs@((label, value):_) =
  let (same, different) = partition ((== label) . fst) xs
  in _

Now that we have the list in these two halves, all that's left to do is (1) decide whether to keep the same chunk or discard it, and (2) call ourselves recursively on different :现在我们有了这两部分的列表,剩下要做的就是 (1) 决定是保留same的块还是丢弃它,以及 (2) 在different上递归调用我们自己:

processList :: [(Char, Bool)] -> [(Char, Bool)]
processList [] = []
processList xs@(x@(label, value):_) =
  let (same, different) = partition ((== label) . fst) xs
      chunk | all (== x) same = same
            | otherwise = []
  in chunk ++ processList different

Finally let's clean up by generalizing from these over-specific types to be polymorphic on Eq types:最后,让我们通过将这些过度特定的类型泛化为Eq类型的多态来进行清理:

removeConflicts :: (Eq a, Eq b) => [[(a, b)]] -> [[(a, b)]]
removeConflicts = map processList

processList :: (Eq a, Eq b) => [(a, b)] -> [(a, b)]
processList [] = []
processList xs@(x@(label, value):_) =
  let (same, different) = partition ((== label) . fst) xs
      chunk | all (== x) same = same
            | otherwise = []
  in chunk ++ processList different

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

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