Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#匹配内存中数据的固定属性_C# - Fatal编程技术网

c#匹配内存中数据的固定属性

c#匹配内存中数据的固定属性,c#,C#,伙计们,这伤了我的脑筋 我在Linq中有一个慢的实现,我需要加快 我需要最快的方法来比较内存(200000)行中的大量只读数据 每行有一个名称和10个表示名称属性的整数 Brake 8 7 3 2 1 0 4 3 2 Skull 8 7 3 2 1 0 4 3 2 Napkin 3 0 5 3 2 1 3 1 0 在任何一个属性中,每个项目都不会超过8个。因此,每个值都可以很好地放入一个double中 例: 现在我的问题是,我需要将这些值与每个字段的最大值进行比较 即: 500000

伙计们,这伤了我的脑筋

我在Linq中有一个慢的实现,我需要加快

我需要最快的方法来比较内存(200000)行中的大量只读数据

每行有一个名称和10个表示名称属性的整数

Brake   8 7 3 2 1 0 4 3 2
Skull   8 7 3 2 1 0 4 3 2
Napkin  3 0 5 3 2 1 3 1 0
在任何一个属性中,每个项目都不会超过8个。因此,每个值都可以很好地放入一个double中

例:

现在我的问题是,我需要将这些值与每个字段的最大值进行比较

即:

500000000将返回前2个和

000001000只会退回餐巾纸,因为其他两个餐巾纸的第4位至少没有1个餐巾纸

我愿意接受任何尽可能快的解决方案。会有很多比较,所以速度是我唯一担心的事情

我当前的实现是这样的:

Items.Where(c => c.A <= 5).Where(c => c.B <= 0).Where(c => c.C <= 0)
.Where(c => c.D <= 0).Where(c => c.E <= 0).Where(c => c.F <= 0)
.Where(c => c.H <= 0).Where(c => c.I <= 0).Where(c => c.J <= 0)

Items.Where(c=>c.A c.B c.c.D c.E c.F c.H c.I c.J c.A事实上,有一种比我原来的答案更好的方法,但它要求每个项目5位,而不是每个项目4位。我将用16位值中的三个项目来说明。您可以使用长整数的前50位将其扩展到10个项目

假设您将三个4位计数器保存在一个16位整数中。每个计数器都有一个用于计算的附加位(请参见下文)。因此,包含前三个计数器的制动项为:

       3     7     8
Brake 00011 00111 01000
         4     0     5
Search 00100 00000 00101
现在,您需要匹配“504”的内容,即第一列中至少有五个项目,第二列中有任意数字,第三列中至少有四个。该掩码为:

       3     7     8
Brake 00011 00111 01000
         4     0     5
Search 00100 00000 00101
从逻辑上讲,我们希望从制动器中减去搜索,并知道所有必填字段是否大于或等于零。这就是额外位的来源。如果我们在每个字段上设置额外位,我们有:

Brake 10011 10111 11000
现在,如果我们在这种情况下做减法,我们得到:

Brake - Search = 01111 10111 10011
请注意,结果最左侧字段中的高位为0。这表示该字段中的制动值小于我们要查找的值

现在,如何在代码中工作。在我的示例中,使用
short
,我有:

short Brake = (short)((3 << 10) | (7 << 5) | 8);
short Search = (short)((4 << 10) | (0 << 5) | 5);

short CarryMask = 0x4210;  // sets the high bit in each field.
                           // corresponds to 0100001000010000

// This would have to be done for each value that you want to compare.
short MaskedValue = (short)(Brake | CarryMask);
short diff = (short)(MaskedValue - Search);
short rslt = (short)(CarryMask & diff);

// rslt should equal CarryMask
if (rslt == CarryMask)
{
    // All fields match
}
else
{
    // At least one field doesn't match
}
我假设您有某种格式的数据,您可以方便地将每个项的字段值放入一个10字节的数组中。您需要添加一个保存组合值的
CombinedValue
属性。或者,您可能有一个并行数据结构来保存组合值。无论如何,您必须在p执行此循环一次程序启动以创建用于比较的数据(或者如果可以更新单个字段,则可能更新值)

我也会假设,当需要搜索时,您可以将要搜索的值放入字节数组中,然后调用
CreateValue
来获得要搜索的组合值。现在您所需要的只是进行比较的方法

// Carry mask has every 5th bit set.
// This is actually the mask for 12 values.
// That's okay, since nothing will affect those higher bits.
const long CarryMask = 0x842108421084210L;

bool ItemMatches(long itemValue, long searchFor)
{
    long maskedValue = itemValue | CarryMask;
    long diff = maskedValue - searchFor;
    long rslt = diff & CarryMask;
    return (rslt == CarryMask);
}
因此,搜索列表变得非常简单:

long searchFor = CreateValue(array_of_values);
foreach (var item in items)
{
    if (ItemMatches(item.CombinedValue, searchFor)
    {
        // The item matches the criteria you specified
    }
}

您的数据由以下结构表示:

public abstract class Widget
{
  public string Name   { get ; private set ; }
  public byte[] Values { get ; private set ; }
}
无论是一个字节数组,还是从中提取的位字段,我怀疑与性能无关

一种方法是构建8个并行数组,其中包含对小部件的引用,每个这样的数组在不同的值列上排序

另一种方法是读取源数据一次,然后填充一个高度平衡的二进制搜索树数组,其键是所需列的值,其值是共享该特定列值的窗口小部件列表。每个列都需要一个这样的搜索树。显然,这种方法会消耗内存以获得快速查找在高度平衡二叉树中,是一种O(logn)操作。使用树意味着可以向集合中添加项或从集合中删除项,而不会产生大量开销

虽然您可以编写自己的树实现,但我不愿意。下面是一个实现,使用(您的工具箱中应该有的东西),因为我讨厌发明轮子:

using System;
using System.Collections.Generic;

using C5;

namespace ConsoleApplication13
{

    class Program
    {

        static void Main( string[] args )
        {
            IEnumerable<Widget>  sourceData  = ReadWidgets();
            WidgetSearcher lookup = new WidgetSearcher( sourceData );

            // find all the Widgets where column 2 is >= 5 ;
            Widget[] results1 = lookup.Search( 2 , 5 ).ToArray();

            // find all the Widgets where column 0 is >= 3 ;
            Widget[] results2 = lookup.Search( 0 , 3 ).ToArray();

            return ;

        }

        private static IEnumerable<Widget> 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;
        }
        /// <summary>
        /// private constructor for search instances
        /// </summary>
        /// <param name="column"></param>
        /// <param name="value"></param>
        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<Widget> , IEqualityComparer<Widget>
        {
            private int ColumnToCompare;

            public Comparer( int colNum )
            {
                if ( colNum<0||colNum>=Widget.ValueCount )
                    throw new ArgumentOutOfRangeException( "colNum" );
                this.ColumnToCompare=colNum;
            }

            #region IComparer<Widget> Members

            public int Compare( Widget x , Widget y )
            {
                return (int)x._values[this.ColumnToCompare]-(int)y._values[this.ColumnToCompare];
            }

            #endregion

            #region IEqualityComparer<Widget> 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<Widget>[] lookups;

        public WidgetSearcher( IEnumerable<Widget> sourceData )
        {
            this.lookups=InstantiateLookups();
            PopulateLookups( sourceData );

        }

        private TreeBag<Widget>[] InstantiateLookups()
        {
            C5.TreeBag<Widget>[] instance =new C5.TreeBag<Widget>[Widget.ValueCount];

            for ( int i = 0 ; i<instance.Length ; ++i )
            {
                Widget.Comparer widgetComparer = new Widget.Comparer( i );

                instance[i]=new TreeBag<Widget>( widgetComparer , widgetComparer );

            }

            return instance;
        }

        private void PopulateLookups( IEnumerable<Widget> sourceData )
        {
            foreach ( Widget datum in sourceData )
            {
                for ( int i = 0 ; i<Widget.ValueCount ; ++i )
                {
                    lookups[i].Add( datum );
                }
            }
            return;
        }

        public IDirectedCollectionValue<Widget> Search( int column , byte value )
        {
            Widget limit = Widget.CreateSearchInstance( column , value );
            return lookups[column].RangeFrom( limit );
        }

    }

}
使用系统;
使用System.Collections.Generic;
使用C5;
命名空间控制台应用程序13
{
班级计划
{
静态void Main(字符串[]参数)
{
IEnumerable sourceData=ReadWidgets();
WidgetSearcher查找=新建WidgetSearcher(sourceData);
//查找第2列>=5的所有小部件;
Widget[]results1=lookup.Search(2,5.ToArray();
//查找列0大于等于3的所有小部件;
Widget[]results2=lookup.Search(0,3.ToArray();
返回;
}
私有静态IEnumerable ReadWidgets()
{
//TODO:我们需要某个地方的源数据。它在这里提供。
抛出新的NotImplementedException();
}
}
公共类小部件
{
public const int ValueCount=8;
公共字符串名称{get;private set;}
公共字节[]值
{
得到
{
返回(字节[])_值。克隆();
}
}
专用字节[]_值;
公共小部件(字符串名称,字节[]值)
{
if(name==null)
抛出新的ArgumentNullException(“名称”);
如果(name.Trim()==“”)
抛出新ArgumentOutOfRangeException(“名称”);
如果(值==null)
抛出新的ArgumentNullException(“值”);
if(values.Length!=ValueCount)
抛出新ArgumentOutOfRangeException(“值”);
this.Name=Name;
这是。_值=值;
返回;
}
/// 
///搜索实例的私有构造函数
/// 
/// 
/// 
私有小部件(int)
public abstract class Widget
{
  public string Name   { get ; private set ; }
  public byte[] Values { get ; private set ; }
}
using System;
using System.Collections.Generic;

using C5;

namespace ConsoleApplication13
{

    class Program
    {

        static void Main( string[] args )
        {
            IEnumerable<Widget>  sourceData  = ReadWidgets();
            WidgetSearcher lookup = new WidgetSearcher( sourceData );

            // find all the Widgets where column 2 is >= 5 ;
            Widget[] results1 = lookup.Search( 2 , 5 ).ToArray();

            // find all the Widgets where column 0 is >= 3 ;
            Widget[] results2 = lookup.Search( 0 , 3 ).ToArray();

            return ;

        }

        private static IEnumerable<Widget> 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;
        }
        /// <summary>
        /// private constructor for search instances
        /// </summary>
        /// <param name="column"></param>
        /// <param name="value"></param>
        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<Widget> , IEqualityComparer<Widget>
        {
            private int ColumnToCompare;

            public Comparer( int colNum )
            {
                if ( colNum<0||colNum>=Widget.ValueCount )
                    throw new ArgumentOutOfRangeException( "colNum" );
                this.ColumnToCompare=colNum;
            }

            #region IComparer<Widget> Members

            public int Compare( Widget x , Widget y )
            {
                return (int)x._values[this.ColumnToCompare]-(int)y._values[this.ColumnToCompare];
            }

            #endregion

            #region IEqualityComparer<Widget> 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<Widget>[] lookups;

        public WidgetSearcher( IEnumerable<Widget> sourceData )
        {
            this.lookups=InstantiateLookups();
            PopulateLookups( sourceData );

        }

        private TreeBag<Widget>[] InstantiateLookups()
        {
            C5.TreeBag<Widget>[] instance =new C5.TreeBag<Widget>[Widget.ValueCount];

            for ( int i = 0 ; i<instance.Length ; ++i )
            {
                Widget.Comparer widgetComparer = new Widget.Comparer( i );

                instance[i]=new TreeBag<Widget>( widgetComparer , widgetComparer );

            }

            return instance;
        }

        private void PopulateLookups( IEnumerable<Widget> sourceData )
        {
            foreach ( Widget datum in sourceData )
            {
                for ( int i = 0 ; i<Widget.ValueCount ; ++i )
                {
                    lookups[i].Add( datum );
                }
            }
            return;
        }

        public IDirectedCollectionValue<Widget> Search( int column , byte value )
        {
            Widget limit = Widget.CreateSearchInstance( column , value );
            return lookups[column].RangeFrom( limit );
        }

    }

}