Hook
Hook

Reputation: 391

Haskell list of list's

I want to compare each item in the list of lists with other elements, for example,

[[1,2,3], [0,2,2], [1,4,5], [3,1,1]] 

compare [1,2,3] to [0,2,2] and applying an operation (for example, the formula of distance "sqrt ((x2-x1)^2+(y2-y1)^2)" and the result of that operation evaluate it with a guard), then compare the [1,2,3] to [1,4,5] and so end the list, then with [0 , 2.2] to [1,4,5] etc ...

I was thinking about taking (head i) and tail (head i) to compare, but do not know how to continue iterating comparisons

can you guys give me an idea about how i can do this? thank you

edit

what i need is this, with the first list of list i need to make another list of list's based on the distance formula and comparing the 3rd element of the list, for example

    [[1,2,3], [0,2,2], [1,4,5], [3,1,1]] 

     [x1,y1,z1], [x2,y2,z2]
    sqrt ((x2-x1)^2+(y2-y1)^2)) if result_of_sqrt < z1 then 1:[do the same thing with the other element]                    
else 0:[do the same thing with the other element]

sqrt ((0-1)^2+(2-2)^2) ) = 1, 1 < 3 => 1:(compare this two elements [1,2,3],[1,4,5]) and so...

Upvotes: 0

Views: 577

Answers (3)

גלעד ברקן
גלעד ברקן

Reputation: 23955

This seems to produce your last example result:

f xs = map (\x -> map (test x) xs) xs
  where test a@[x1,y1,z1] b@[x2,y2,z2] = 
          if a == b 
             then 0 
             else if sqrt ((x2 - x1) ^ 2 + (y2 - y1) ^ 2) < z1 
                     then 1 
                     else 0

Or with guards instead of if and else:

f xs = map (\x -> map (test x) xs) xs
  where test a@[x1,y1,z1] b@[x2,y2,z2] 
          | a == b    = 0 
          | m < z1    = 1 
          | otherwise = 0
    where m = sqrt ((x2 - x1) ^ 2 + (y2 - y1) ^ 2)

Output:

*Main> f [[0,0,4], [2,4,2], [1,3,5], [3,1,1]]
[[0,0,1,1],[0,0,1,0],[1,1,0,1],[0,0,0,0]]

Upvotes: 2

iamnat
iamnat

Reputation: 4166

I'm not sure if I've understood you correctly, but perhaps this will help you figure something out:

  1. Pair up all the tuples
  2. Apply your 'comparison' function to those tuples and output a true/false

.

lol :: [(Int,Int,Int)]
lol =  [(1,2,3), (0,2,2), (1,4,5), (3,1,1)]

-- Use list comprehension to get all your unique pairs
tuples = [(x,y) | x <- lol, y <- lol, x > y]

result = map myCompare tuples

-- myCompare takes a tuple of two 3-vector tuples and does an operation on them
-- It outputs the two vectors it and a True/False
myCompare (x@(x1,y1,z1),y@(x2,y2,z2)) = if ( (x1-x2)^2 + (y1-y2)^2 < (z2-z1)^2 ) then (x,y,True) else (x,y,False)       

Outputs:

tuples = [((1,2,3),(0,2,2)),((1,4,5),(1,2,3)),((1,4,5),(0,2,2)),((3,1,1),(1,2,3)),((3,1,1),(0,2,2)),((3,1,1),(1,4,5))]

result = [((1,2,3),(0,2,2),False),((1,4,5),(1,2,3),False),((1,4,5),(0,2,2),True),((3,1,1),(1,2,3),False),((3,1,1),(0,2,2),False),((3,1,1),(1,4,5),True)]

Upvotes: 1

Benjamin Kovach
Benjamin Kovach

Reputation: 3260

The question is really unclear, but it sounds like, at a fundamental level, you want to take each element of a list and compare it to all of the rest of elements in the list. Say we want to pair all of the elements in [1..3] where order doesn't matter, i.e. we want the list:

`[(1, 2), (1, 3), (2, 3)]`

We can do this directly:

pairAll :: [a] -> [(a, a)]
pairAll [] = []
pairAll (x:xs) = map (\y -> (x, y)) xs ++ pairAll xs

Now pairAll [1..3] == [(1, 2), (1, 3), (2, 3)] as desired. We can factor out the pairing function to get:

doStuffToAll :: (a -> a -> b) -> [a] -> [b]
doStuffToAll _ [] = []
doStuffToAll f (x:xs) = map (f x) xs ++ doStuffToAll f xs

And then pairAll = doStuffToAll (\x y -> (x, y)).

Replace the lambda expression with your comparison function for lists (i.e. doStuffWithAll compareLists), and that should do it, if I understand your question properly.

Upvotes: 4

Related Questions