Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most efficient way to create the Data.Set of all pairs of elements in a Set?

Given an arbitrary set holding an arbitrary number of elements of arbitrary type, e.g.

mySet1 = Set.fromList [1,2,3,4]

or

mySet2 = Set.fromList ["a","b","c","d"]

or

mySet3 = Set.fromList [A, B, C, D]

for some data constructors A, B, C, D, ...

What is the computationally most efficient way to generate the set of all unordered pairs of elements is the given set? I.e.

setPairs mySet1 == Set.fromList [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]

or

setPairs mySet2 == fromList [ ("a","b")
                            , ("a","c")
                            , ("a","d")
                            , ("b","c")
                            , ("b","d")
                            , ("c","d") ]

or

setPairs mySet2 == fromList [ (A,B)
                            , (A,C)
                            , (A,D)
                            , (B,C)
                            , (B,D)
                            , (C,D) ]

My initial naive guess would be:

setPairs s = fst $ Set.fold
    (\e (pairAcc, elementsLeft) ->
        ( Set.fold
              (\e2 pairAcc2 ->
                  Set.insert (e2, e) pairAcc2
              ) pairAcc $ Set.delete e elementsLeft
        , Set.delete e elementsLeft )
    ) (Set.empty, s) s

but surely that cannot be the best solution?

like image 346
Josephine Avatar asked Nov 21 '11 13:11

Josephine


People also ask

How do you create an array of pairs?

For example pair-sum array for arr[] = {6, 8, 3, 4} is {14, 9, 10, 11, 12, 7}. In general, pair-sum array for arr[0..n-1] is {arr[0]+arr[1], arr[0]+arr[2], ……., arr[1]+arr[2], arr[1]+arr[3], ……., arr[2]+arr[3], arr[2]+arr[4], …., arr[n-2]+arr[n-1}.

How do you create a set of sets in Python?

To represent a set of sets, the inner sets must be frozenset objects for the reason that the elements of a set must be hashable (all of Python's immutable built-in objects are hashable). frozenset is immutable and set is mutable.

How do you find the elements of a set in Python?

You cannot access items in a set by referring to an index or a key. But you can loop through the set items using a for loop, or ask if a specified value is present in a set, by using the in keyword.

What is set () Python?

Python | set() method set() method is used to convert any of the iterable to sequence of iterable elements with distinct elements, commonly called Set. Syntax : set(iterable) Parameters : Any iterable sequence like list, tuple or dictionary. Returns : An empty set if no element is passed.


1 Answers

Benchmarking might prove me wrong, but my suspicion is that there's no win in staying in the set representation. You're going to need O(n^2) regardless, because that's the size of the output. The key advantage would be producing your list such that you could use a call to S.fromDistinctAscList such that it only costs O(n) to build the set itself.

The following is pretty clean, preserves a fair amount of sharing, and is generally the simplest, most straightforward and intuitive solution I can imagine.

pairs s = S.fromDistinctAscList . concat $ zipWith zip (map (cycle . take 1) ts) (drop 1 ts)
   where ts = tails $ S.toList s

Edit

Shorter/clearer (not sure performancewise, but probably as good/better):

pairs s = S.fromDistinctAscList [(x,y) | (x:xt) <- tails (S.toList s), y <- xt]
like image 60
sclv Avatar answered Sep 27 '22 00:09

sclv