user12117801
user12117801

Reputation:

How to filter indexes in a list?

For example, if I have a list of

[2,2,3,5,4,6]

and I filter for even numbers, I want to output the indexes of those numbers:

[1,2,5,6]

I know about the filter function which return the elements. How can I get their indexes instead? I have defined the fuction index which return the elements with their indexes as tuplets. Any hints how should I continue?

index x = [ n | n <- [ zip x [1..]]]

Upvotes: 1

Views: 283

Answers (2)

Andra
Andra

Reputation: 1392

First, you can give the index of a list using zip. From the list with index, we can filter the list that has a even value. After that we can extract the value.

-- Will be (Value, Index) tuple
withIndex :: [Int] -> [(Int, Int)]
withIndex x = zip x [1..]

main =
    print (
        map snd (
            filter
                (even . fst)
                (withIndex [2, 2, 3, 5, 4, 6])
        )
    )

https://ideone.com/GDmW6j

Upvotes: 0

Will Ness
Will Ness

Reputation: 71075

In your code,

index x = [ n | n <- [ zip x [1..] ] ]

the [ n | n <- [ e ]] is equivalent to [ n | let n=e ] is equivalent to let n = e in [n] or just [e], i.e. [zip x [1..]]. It's not what you want.

The

index x = [ n | n <- ( zip x [1..] ) ]

on the other hand, is different. The parens are used for grouping, and as such are superfluous and can be omitted here. The code then is equivalent to [ n | n <- e ] which is equivalent to just e i.e. zip x [1..], which is a step closer.

You just need to deconstruct the n, which is a pair of an element and an index (constructed by zip), and include an index if the element is even, in the output list.

We deconstruct values by pattern matching.

A pair pattern is written (a,b), or (e,i), etc.

Upvotes: 1

Related Questions