Home > front end >  How can I go through a list of numbers and compare it with an another list I am going through?
How can I go through a list of numbers and compare it with an another list I am going through?

Time:02-03

I want to input two strings, "Hello" and "Hi" for example, and I want to go through every element in the two strings simultaneously and compare every character one by one. The two strings length in the actual program should be 5, if a char is equal to the other, return true, otherwise return false.

The program I have in mind should see 'H' in "Hello" and 'H' from "Hi" and return true, then I want it to check the 'e' in "Hello" and the 'i' in "Hi" and return false. I want it to keep on doing that till there is nothing to compare. I think I might need to use recursion but I am not sure how to implement it in this program really.

I tried using x:xs with the maximum range of 5 so [0..5], but it didn't work at all.

My code (not working):

uncurryingString :: String -> Int -> Char
uncurryingString a b = a !! b

match :: String -> String -> [Int] -> Bool 
match a b (x:xs)
            |   uncurryingString a [x 1 | x <- xs]  == uncurryingString b [x 1 | x <- xs]       = True
            |   otherwise                                                                       = False 

CodePudding user response:

You're thinking about this way too complicated.

First, as a rule of thumb, you should never use !! (whether directly or via some helper – uncurryingString is in fact exactly the same as !! itself). If direct indexing is required, a list is not the right data structure. But very often direct indexing is not required, it's just what's customarily used in some other programming languages that don't have pattern matching to do it more elegantly.

In your application, you're deconstructing both strings in parallel. Well, you should express that with a pattern match:

match (a:as) (b:bs) (x:xs) = ...

And now you can simply compare a and b directly, no need for messing about with any list comprehensions or indexing operators. In the example input "Hello" and "Hi", both a and b will be 'H' here.

But you probably don't want to return True right there, because there's still the rest of the string to be matched. That's where recursion comes in.

Finally, you need to clauses in case not all of the input lists are nonempty. Try to figure that out yourself.

What you probably don't need at all is the extra [Int] argument (x:xs). It could make sense to have a depth-limiting argument, but that could be simply an Int. You would then do something like

match :: Eq a => [a] -> [a] -> Int -> Bool
match _ _ 0 = True    -- lists are equal up to the specified max depth
match (a:as) (b:bs) n = ...
...

CodePudding user response:

Using a list comprehension is often a good way to compute things in Haskell, but not in this particular case.

I could try this code:

 [a==b | a <- "Hello", b <- "Hi"]

What does this do? You might think that this returns True, because the 'H' letters match - or you might thing that this returns False, because the other letters don't match. In fact, it does both - in effect, it is running multiple nested loops.

[True,False,False,False,False,False,False,False,False,False]

So, the takeaway is to use list comprehensions when you want nested loops, or just working through one dataset. Here we just want a single loop that works through the two words in parallel. Hence it must be recursion.

  •  Tags:  
  • Related