Click here to Skip to main content
Click here to Skip to main content

Tagged as

Permutations of Dictionary Items

, 23 Sep 2013
Rate this:
Please Sign up or sign in to vote.
Generate every permutation of dictionary items.

Introduction

In this article, I will present an easy to use method for iterating over all permutations of a model.  Each model parameter is defined as an entry into a Dictionary(of String, Object). Any number model parameters can be used as input and the output is a Dictionary(of Integer, Object) where the integer key is the permutation number and the object is another dictionary that contains the model parameters for that permutation.  This is useful is in providing every possible set of inputs into a function.

Background

Other permutation examples will give you every instance of a string or integer array.  What if your inputs are more complex? By using a Dictionary(of String, Object) for model inputs a name for the parameter can be defined and the parameters can be anything from a simple array, true/false values, a class, or a structure.

Using the code

Examples here are in VB.  Download for the C# project for C# code.

Use the code by defining a Dictionary(of String, Object) inputs:

Dim d As New Dictionary(Of String, Object)

Dim b() As Boolean = {True, False}
d.Add("IsMarried", b)
d.Add("IsEmployed", b)

d.Add("YearsAtAddress", {2, 5, 10})
d.Add("IncomeLevel", {25000, 50000, 75000, 100000})

Dim cb As New List(Of Credit)
cb.Add(New Credit With {.Bureau = "Equifax", .ScoreAvg = 500})
cb.Add(New Credit With {.Bureau = "Equifax", .ScoreAvg = 600})
cb.Add(New Credit With {.Bureau = "Equifax", .ScoreAvg = 700})
cb.Add(New Credit With {.Bureau = "Transunion", .ScoreAvg = 500})
cb.Add(New Credit With {.Bureau = "Transunion", .ScoreAvg = 600})
cb.Add(New Credit With {.Bureau = "Transunion", .ScoreAvg = 700})
d.Add("Credit", cb) 

Then call the function:

Dim ps As Dictionary(Of Integer, Object) = PermutateDictionary.Permutations(d) 

The result is a dictionary containing all the permutations and the parameters for each. 

1: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 25000(IncomeLevel) Equifax-500(Credit)
2: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 25000(IncomeLevel) Equifax-600(Credit)
3: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 25000(IncomeLevel) Equifax-700(Credit)
4: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 25000(IncomeLevel) Transunion-500(Credit)
5: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 25000(IncomeLevel) Transunion-600(Credit)
6: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 25000(IncomeLevel) Transunion-700(Credit)
7: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 50000(IncomeLevel) Equifax-500(Credit)
8: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 50000(IncomeLevel) Equifax-600(Credit)
9: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 50000(IncomeLevel) Equifax-700(Credit)
10: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 50000(IncomeLevel) Transunion-500(Credit)
11: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 50000(IncomeLevel) Transunion-600(Credit)
12: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 50000(IncomeLevel) Transunion-700(Credit)
13: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 75000(IncomeLevel) Equifax-500(Credit)
14: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 75000(IncomeLevel) Equifax-600(Credit)
15: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 75000(IncomeLevel) Equifax-700(Credit)
16: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 75000(IncomeLevel) Transunion-500(Credit)
17: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 75000(IncomeLevel) Transunion-600(Credit)
18: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 75000(IncomeLevel) Transunion-700(Credit)
19: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 100000(IncomeLevel) Equifax-500(Credit)
20: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 100000(IncomeLevel) Equifax-600(Credit)
21: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 100000(IncomeLevel) Equifax-700(Credit)
22: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 100000(IncomeLevel) Transunion-500(Credit)
23: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 100000(IncomeLevel) Transunion-600(Credit)
24: True(IsMarried) True(IsEmployed) 2(YearsAtAddress) 100000(IncomeLevel) Transunion-700(Credit)
.
.
.
281: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 75000(IncomeLevel) Transunion-600(Credit)
282: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 75000(IncomeLevel) Transunion-700(Credit)
283: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 100000(IncomeLevel) Equifax-500(Credit)
284: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 100000(IncomeLevel) Equifax-600(Credit)
285: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 100000(IncomeLevel) Equifax-700(Credit)
286: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 100000(IncomeLevel) Transunion-500(Credit)
287: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 100000(IncomeLevel) Transunion-600(Credit)
288: False(IsMarried) False(IsEmployed) 10(YearsAtAddress) 100000(IncomeLevel) Transunion-700(Credit) 

The code to produce the output is:

For Each p In ps
    Console.Write(CStr(p.Key) + ": ")
    For Each e In p.Value
        If TypeName(e.value) = "Credit" Then
            Console.Write(CStr(e.value.Bureau + "-" + _
                          e.value.ScoreAvg.ToString) + "(" + e.key + ") ")
        Else
            Console.Write(CStr(e.value) + "(" + e.key + ") ")
        End If
    Next
    Console.WriteLine()
Next

The code that does the work is:

Public Class PermutateDictionary

    Shared Function Permutations(ds As Dictionary(Of String, Object)) _
        As Dictionary(Of Integer, Object)

        Dim pCount As Integer = 1
        Dim sPointer As New Dictionary(Of String, Integer)
        Dim pNumber As Integer
        Dim result As New Dictionary(Of Integer, Object)

        For Each d In ds

            pCount *= GetEntryCount(d)
            sPointer.Add(d.Key, 0)
        Next

        For pNumber = 1 To pCount

            Dim pEntry As New Dictionary(Of String, Object)
            For Each d In ds
                pEntry.Add(d.Key, d.Value(sPointer(d.Key)))
            Next
            result.Add(pNumber, pEntry)

            'Iterate and increment the pointers
            For Each d In ds.Reverse
                sPointer(d.Key) += 1
                If sPointer(d.Key) = GetEntryCount(d) Then
                    sPointer(d.Key) = 0
                Else
                    Exit For
                End If
            Next
        Next
        Return result

    End Function

    Private Shared Function GetEntryCount(ByRef Entry As Object) _
        As Integer

        Try
            Return Entry.Value.length
        Catch ex As Exception
            Return Entry.Value.count
        End Try
    End Function
End Class
 

Download the sample project.  I hope you find this useful. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

RoarkDude

United States United States
Software developer since 1981. Currently specializing in VB and .NET.

Comments and Discussions

 
QuestionRe: Files PinmemberKalkidas26-Sep-13 9:57 
AnswerRe: Files PinmemberRoarkDude26-Sep-13 10:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 23 Sep 2013
Article Copyright 2013 by RoarkDude
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid