Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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# 实现自定义Int+;范围列表解决方案_C#_List_Range - Fatal编程技术网

C# 实现自定义Int+;范围列表解决方案

C# 实现自定义Int+;范围列表解决方案,c#,list,range,C#,List,Range,我想知道是否有人能想出一种方法,以一种更节省内存的方式实现一个数字数组,从而自动将其组织到各个范围中。榜样 List testList = new List{1,2,3,4,5,6,7...}; vs 特定于我的实施的详细信息 在我的特殊情况下,我正在逐行分析一个非常大的文档。需要识别满足特定标准的行,然后向用户显示行索引的总体列表 显然,显示“第33-32019行已识别”比显示“第33、34、35行……等”更可取。在这种情况下,数字总是正的。我要做的第一件事是创建一个代表您的范围的类。您可以

我想知道是否有人能想出一种方法,以一种更节省内存的方式实现一个数字数组,从而自动将其组织到各个范围中。榜样

List testList = new List{1,2,3,4,5,6,7...};
vs

特定于我的实施的详细信息

在我的特殊情况下,我正在逐行分析一个非常大的文档。需要识别满足特定标准的行,然后向用户显示行索引的总体列表


显然,显示“第33-32019行已识别”比显示“第33、34、35行……等”更可取。在这种情况下,数字总是正的。

我要做的第一件事是创建一个代表您的范围的类。您可以提供一些便利,比如将格式设置为字符串,以及从int进行隐式转换(这有助于以后实现范围列表)

然后可以开始执行
范围列表的简单实现。通过提供
Add
方法,您可以使用类似于
list
的列表初始值设定项:

这方面的实例:

接下来要做的事情是提供一个重载
Add
,它接受一个int并找到正确的范围或添加一个新的范围。一个简单的实现可能如下所示(假设在范围上添加了
Update
方法)

每次更改列表后都需要调用此函数

public void Add(Range range)
{
    this.ranges.Add(range);
    SortAndMerge();
}

public void Add(int value)
{
    // is it within or contiguous to an existing range
    foreach(var range in ranges)
    {
        if(value>=range.Start && value<=range.End)
            return; // already in a range
        if(value == range.Start-1)
        {
            range.Update(value,range.End);
            SortAndMerge();
            return;
        }
        if(value == range.End + 1)
        {
            range.Update(range.Start,value);
            SortAndMerge();
            return;
        }
    }
    // not in any ranges
    ranges.Add(value);
    SortAndMerge();
}
public void Add(范围)
{
this.ranges.Add(范围);
SortAndMerge();
}
公共void Add(int值)
{
//它是在现有范围内还是邻近现有范围
foreach(范围中的var范围)
{

如果(value>=range.Start&&value)您的数字是负数吗?还是符号位为“备用”我认为这在很大程度上取决于类的使用。如果你很少添加/删除新的项目,我会把它重点放在获取/计算/任意的性能上,以及在添加项目时总是关注添加/组织的性能。我想这个问题有点太宽泛了。有很多事情要考虑。:如何表示
范围
(元组,额外类型)?列表通常包含相同类型的元素,因此您需要考虑是否要将单个整数添加为长度为1的
范围
…可能需要(隐式)将运算符从
int
转换为
Range
…您需要为列表实现一个枚举器来枚举包含的范围…这是一个有趣的想法,但意味着要为您编写大量代码…所以我仍然认为它太宽泛了。@MatthewWatson问得好,总是肯定的。请参阅我的更新。@RenéVogt我明白您的观点。然而,我可以人为地限制这个问题,使其更加具体,但我认为这不会有帮助。我已经在我的用例描述中添加了,如果这使它更“真实”。这与我的想法非常相似,但是请注意,您还必须提供更新现有范围的方法(因此,将起点和终点设为私有setter是错误的)或将其替换为新的范围(请注意,这在问题中是特别需要的).别忘了处理合并-假设您已经有1..10和12..20,然后添加11@windowskm我想给你写一个更好的
Add
,它勾选了所有的框…但是我的大楼里的火警刚刚响了:D可能是个延迟!哇,绝对不是紧急的,所以别担心。保重,希望一切都好。@windowskm哈,没问题。仍然没有疏散。高层办公室的乐趣。无论如何,我更新了我的答案。如果有任何问题,请告诉我
RangeList rangeList = new RangeList{1, 4, 7-9};
rangeList.Add(2);
//rangeList -> 1-2, 4, 7-9
rangeList.Add(3);
//rangeList -> 1-3, 4, 7-9
public class Range
{
    public int Start{get; private set;}
    public int End{get; private set;}

    public Range(int startEnd) : this(startEnd,startEnd)
    {           
    }

     public Range(int start, int end)
     {
        this.Start = start;
        this.End = end;
     }

    public static implicit operator Range(int i)
    {
        return new Range(i);
    }

    public override string ToString()
    {
        if(Start == End)
            return Start.ToString();
        return String.Format("{0}-{1}",Start,End);
    }
}
public class RangeList : IEnumerable<Range>
{
    private List<Range> ranges = new List<Range>();

    public void Add(Range range)
    {
        this.ranges.Add(range);
    }

    public IEnumerator<Range> GetEnumerator()
    {
        return this.ranges.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator(){
        return this.GetEnumerator();
    }
}
var rangeList = new RangeList(){
    new Range(1,10),
    15
};

foreach(var range in rangeList)
    Console.WriteLine(range);

// Outputs:
//  1-10
//  15
public void Add(int i)
{
    // is it within or contiguous to an existing range
    foreach(var range in ranges)
    {
        if(i>=range.Start && i<=range.End)
            return; // already in a range
        if(i == range.Start-1)
        {
            range.Update(i,range.End);
            return;
        }
        if(i == range.End + 1)
        {
            range.Update(range.Start,i);
            return;
        }
    }
    // not in any ranges
    ranges.Add(i);
}
private void SortAndMerge()
{
    ranges.Sort((a,b) => a.Start - b.Start);
    var i = ranges.Count-1;
    do
    {
        var start = ranges[i].Start;
        var end = ranges[i-1].End;
        if(end == start-1)
        {
            // merge and remove
            ranges[i-1].Update(ranges[i-1].Start,ranges[i].End);
            ranges.RemoveAt(i);
        }
    } while(i-- >1);
}
public void Add(Range range)
{
    this.ranges.Add(range);
    SortAndMerge();
}

public void Add(int value)
{
    // is it within or contiguous to an existing range
    foreach(var range in ranges)
    {
        if(value>=range.Start && value<=range.End)
            return; // already in a range
        if(value == range.Start-1)
        {
            range.Update(value,range.End);
            SortAndMerge();
            return;
        }
        if(value == range.End + 1)
        {
            range.Update(range.Start,value);
            SortAndMerge();
            return;
        }
    }
    // not in any ranges
    ranges.Add(value);
    SortAndMerge();
}
public void Add(Range rangeToAdd)
{
    var mergableRange = new List<Range>();
    foreach (var range in ranges)
    {
        if (rangeToAdd.Start == range.Start && rangeToAdd.End == range.End)
            return; // already exists

        if (mergableRange.Any())
        {
            if (rangeToAdd.End >= range.Start - 1)
            {
                mergableRange.Add(range);
                continue;
            }
        }
        else
        {
            if (rangeToAdd.Start >= range.Start - 1
                && rangeToAdd.Start <= range.End + 1)
            {
                mergableRange.Add(range);
                continue;
            }

            if (range.Start >= rangeToAdd.Start
                && range.End <= rangeToAdd.End)
            {
                mergableRange.Add(range);
                continue;
            }
        }
    }

    if (!mergableRange.Any()) //Standalone range
    {
        ranges.Add(rangeToAdd);
    }
    else //merge overlapping ranges
    {
        mergableRange.Add(rangeToAdd);
        var min = mergableRange.Min(x => x.Start);
        var max = mergableRange.Max(x => x.End);
        foreach (var range in mergableRange) ranges.Remove(range);
        ranges.Add(new Range(min, max));
    }

    SortAndMerge();
}