Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data structure to contain data indexed by column and row string indexes

I have a list of objects to display to the user. Basically, it is a set of permissions by user. I want to display a table with users as columns and actions as rows. Then the permission would be displayed at the intersection between the user and action.

I am looking for a way to represent this data in a C# data structure. It would allow access using user (string) and action (string), as well as provide a default value for each "cell". Ideally, it would be bound to a Grid Control with automatic column creation.

An array would be great but it only allow integers as indexes. It would also require recreating and copying the array when a new row/column is added.

I thought about creating a Dictionary<String, Dictionary<String, Permission>> object, but it requires a lot of error checking and does not work well with datagrid controls.

Is there an existing (open source?) project for that kind of data structure? Basically, it is just an enhanced version of a "value with two-keys" structure.

Thank you

like image 294
Johann Blais Avatar asked Jun 03 '11 13:06

Johann Blais


People also ask

Which data structure has both row and column?

A DataFrame is a two-dimensional data structure composed of rows and columns — exactly like a simple spreadsheet or a SQL table. Each column of a DataFrame is a pandas Series.

What data structure is indexed?

Data structures for indexingB-trees are the most commonly used data structures for indexes as they are time-efficient for lookups, deletions, and insertions. All these operations can be done in logarithmic time. Data that is stored inside of a B-tree can be sorted.

What does it mean for a column to be indexed?

An index is a copy of selected columns of data, from a table, that is designed to enable very efficient search. An index normally includes a "key" or direct link to the original row of data from which it was copied, to allow the complete row to be retrieved efficiently.


1 Answers

If you want a data structure that is friendly to grid controls with automatic column generation, then the data structure of choice is a DataTable. A DataTable is like a dynamic two-dimensional array of data organized by rows and columns which is exactly what you want. If fact the columns are indexed by strings, which is also what you want. All we need to do if find a way to address the rows of a DataTable by string and we'll be all set!

Here's an implementation of a PermissionMap which is a DataTable so you can use it with grid controls, but it also has some infrastructure to support indexing by two strings. The exact approach can vary, but the basic idea is to start with a DataTable and then add:

  • A constructor that supplies the user actions
  • An AddUser method to add new users and set the default permissions
  • A two parameter indexer to get and set permissions by user and action

Here's a sample implementation:

public enum Permission
{
    Default = 0,
    Disallow = 0,
    Allow = 1,
}

public class PermissionMap : DataTable
{
    private Dictionary<string, int> actionMap = new Dictionary<string, int>();

    public PermissionMap(IEnumerable<string> actions)
    {
        Columns.Add(new DataColumn("Action"));
        int i = 0;
        foreach (var action in actions)
        {
            actionMap.Add(action, i++);
            var row = NewRow();
            row["Action"] = action;
            Rows.Add(row);
        }
    }

    public void AddUser(string user)
    {
        Columns.Add(new DataColumn(user));
        foreach (DataRow row in Rows)
            row[user] = Permission.Default;
    }

    public Permission this[string user, string action]
    {
        get { return (Permission)Rows[actionMap[action]][user]; }
        set { Rows[actionMap[action]][user] = value; }
    }
}

And here's a little demonstration program:

class Program
{
    static void Main(string[] args)
    {
        var permissionMap = new PermissionMap(new[] { "Read", "Write" });
        permissionMap.AddUser("Bill");
        permissionMap.AddUser("Jane");
        permissionMap["Bill", "Read"] = Permission.Allow;
        permissionMap["Jane", "Write"] = Permission.Allow;
        foreach (DataColumn column in permissionMap.Columns)
        {
            Console.Write(column.ColumnName);
            Console.Write(",");
        }
        Console.WriteLine();
        foreach (DataRow row in permissionMap.Rows)
        {
            foreach (DataColumn column in permissionMap.Columns)
            {
                Console.Write(row[column]);
                Console.Write(",");
            }
            Console.WriteLine();
        }
        Console.ReadKey();
    }
}

which produces this output:

Action,Bill,Jane,
Read,Allow,Disallow,
Write,Disallow,Allow,
like image 115
Rick Sladkey Avatar answered Oct 12 '22 23:10

Rick Sladkey