Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Your data is represented by a structure that resembles this:</p> <pre><code>public abstract class Widget { public string Name { get ; private set ; } public byte[] Values { get ; private set ; } } </code></pre> <p>Whether it's an array of bytes, or a bit field that you draw from is, I suspect fairly irrelevant to performance.</p> <p>One approach would be to build 8 parallel arrays containing references to your widgets with each such array being sorted on a different value column. Lookup then consisted of a binary search for the desired values.</p> <p>Another approach is to read your source data once, and populate an array of height-balanced binary search trees, whose key is the value of the desired column and whose value is the list of Widgets sharing that particular column value. You'll need one such search tree for each column. Obviously, this approach eats memory to get speed &mdash; lookup in a height-balance binary tree being a O(log <em>N</em>) operation. Using trees means that items can be added to and removed from the collection without imposing a lot of overhead.</p> <p>Whilst you <strong>could</strong> write your own tree implementation, I'd rather not. Here is an implementation, using the <a href="http://www.itu.dk/research/c5/" rel="nofollow">C5 Collections Library</a> (something you should have in your toolbox anyway) since I hate having to invent the wheel:</p> <pre><code>using System; using System.Collections.Generic; using C5; namespace ConsoleApplication13 { class Program { static void Main( string[] args ) { IEnumerable&lt;Widget&gt; sourceData = ReadWidgets(); WidgetSearcher lookup = new WidgetSearcher( sourceData ); // find all the Widgets where column 2 is &gt;= 5 ; Widget[] results1 = lookup.Search( 2 , 5 ).ToArray(); // find all the Widgets where column 0 is &gt;= 3 ; Widget[] results2 = lookup.Search( 0 , 3 ).ToArray(); return ; } private static IEnumerable&lt;Widget&gt; ReadWidgets() { //TODO: we need source data from somewhere. It gets provided here. throw new NotImplementedException(); } } public class Widget { public const int ValueCount = 8; public string Name { get; private set; } public byte[] Values { get { return (byte[])_values.Clone(); } } private byte[] _values; public Widget( string name , byte[] values ) { if ( name==null ) throw new ArgumentNullException( "name" ); if ( name.Trim()=="" ) throw new ArgumentOutOfRangeException( "name" ); if ( values==null ) throw new ArgumentNullException( "values" ); if ( values.Length!=ValueCount ) throw new ArgumentOutOfRangeException( "values" ); this.Name=name; this._values=values; return; } /// &lt;summary&gt; /// private constructor for search instances /// &lt;/summary&gt; /// &lt;param name="column"&gt;&lt;/param&gt; /// &lt;param name="value"&gt;&lt;/param&gt; private Widget( int column , byte value ) { this.Name=null; this._values=new byte[Widget.ValueCount]; this._values.Initialize(); this._values[column]=value; return; } public class Comparer : IComparer&lt;Widget&gt; , IEqualityComparer&lt;Widget&gt; { private int ColumnToCompare; public Comparer( int colNum ) { if ( colNum&lt;0||colNum&gt;=Widget.ValueCount ) throw new ArgumentOutOfRangeException( "colNum" ); this.ColumnToCompare=colNum; } #region IComparer&lt;Widget&gt; Members public int Compare( Widget x , Widget y ) { return (int)x._values[this.ColumnToCompare]-(int)y._values[this.ColumnToCompare]; } #endregion #region IEqualityComparer&lt;Widget&gt; Members public bool Equals( Widget x , Widget y ) { return ( x._values[this.ColumnToCompare]==x._values[this.ColumnToCompare] ); } public int GetHashCode( Widget obj ) { return obj._values[this.ColumnToCompare].GetHashCode(); } #endregion } internal static Widget CreateSearchInstance( int column , byte value ) { return new Widget( column , value ); } } public class WidgetSearcher { private C5.TreeBag&lt;Widget&gt;[] lookups; public WidgetSearcher( IEnumerable&lt;Widget&gt; sourceData ) { this.lookups=InstantiateLookups(); PopulateLookups( sourceData ); } private TreeBag&lt;Widget&gt;[] InstantiateLookups() { C5.TreeBag&lt;Widget&gt;[] instance =new C5.TreeBag&lt;Widget&gt;[Widget.ValueCount]; for ( int i = 0 ; i&lt;instance.Length ; ++i ) { Widget.Comparer widgetComparer = new Widget.Comparer( i ); instance[i]=new TreeBag&lt;Widget&gt;( widgetComparer , widgetComparer ); } return instance; } private void PopulateLookups( IEnumerable&lt;Widget&gt; sourceData ) { foreach ( Widget datum in sourceData ) { for ( int i = 0 ; i&lt;Widget.ValueCount ; ++i ) { lookups[i].Add( datum ); } } return; } public IDirectedCollectionValue&lt;Widget&gt; Search( int column , byte value ) { Widget limit = Widget.CreateSearchInstance( column , value ); return lookups[column].RangeFrom( limit ); } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload