在列表中找到一系列相同的数字

本文关键字:数字 一系列 列表 | 更新日期: 2023-09-27 18:12:20

我有一个包含1或0的项目列表,我希望仅在列表中有六个背靠背1的地方输出项目。因此,只有当列表中的项目是一组六个项目中的一部分时,才会写入控制台。

11111101110

在上面的列表中,前6个项目将被输出,但底部的3个15不会输出,因为它们不是6个项目的一部分。

这是LINQ或RegEx的工作吗?

在列表中找到一系列相同的数字

您可以将所有值连接成字符串,然后将其除以零。从子字符串中选择至少有6个字符的子字符串:

List<int> values = new List<int> { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
var series = String.Concat(values)
                   .Split(new[] { '0' }, StringSplitOptions.RemoveEmptyEntries)
                   .Where(s => s.Length >= 6);

对于给定的输入数据系列将包含单个项目"111111",您可以将其输出到控制台。

经典运行长度编码,0 (n),延迟求值,堆栈不可知,适用于任何等价类型。

public void TestRunLength()
{
    var runs = new List<int>{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 0, 4};
    var finalGroup = RunLength(runs).FirstOrDefault(i => i.Count == 6 && i.First() == 1);
}
private IEnumerable<List<T>> RunLength<T>(IEnumerable<T> source) where T : IEquatable<T>
{
    T current = default(T);
    var requiresInit = true;
    var list = new List<T>();
    foreach (var i in source)
    {
        if (requiresInit)
        {
            current = i;
            requiresInit = false;
        }
        if (i.Equals(current))
        {
            list.Add(i);
        }
        else
        {
            yield return list;
            list = new List<T>{ i };
            current = i;
        }
    }
    if (list.Any())
    {
        yield return list;
    }
}

因为它是懒惰的,它在无限序列上工作(是的,我知道它不是无限的,但它是大的)!

public void TestRunLength()
{
    var random = new Random();
    var runs = Enumerable.Range(int.MinValue, int.MaxValue)
                         .Select(i => random.Next(0, 10));
    var finalGroup = RunLength(runs)
        .FirstOrDefault(i => i.Count == 6);
}

如果您将数字连接到字符串中,可能也可以使用Regex完成。但是我更喜欢linq:

var bits = new List<int> {1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0};
int bitCountPerGroup = 6;
var result = bits                    // (1)        (2)
            .Select((x,idx) => bits.Skip(idx).TakeWhile(y => y == x))
            .Where(g => g.Count() == bitCountPerGroup); // (3)
foreach (var set in result)
     Console.WriteLine(string.Join(" ", set));

此代码通过从数字(1)开始并取下一个数字,只要它们等于(2),为每个数字获得一个数字集。然后过滤组并仅获得具有6个数字(3)的组。

如果例如你的列表是一个未知的大小,或者更好的,你不知道其中的项目,你可以做这个递归的例子(注意,我放置了更多的零,所以它会获取2组数据,它也与你的工作),并传递给方法的数量分组:

//this is the datastructure to hold the results
static List<KeyValuePair<string, List<int>>> Set = new List<KeyValuePair<string, List<int>>>();
private static void GetData(List<int> lst, int group)
{
    int count = 1;
    int pivot = lst.First();
    if (lst.Count < group)
    {
        return;
    }
    else
    {
        foreach (int i in lst.Skip(1))
        {
            if (i == pivot)
            {
                count++;
            }
            else if (count == group)
            {
                Set.Add(new KeyValuePair<string, List<int>>("Set of items " + pivot, lst.Take(count).ToList()));
                GetData(lst.Skip(count).ToList(), group);
                break;
            }
            else
            {
                GetData(lst.Skip(count).ToList(), group);
                break;
            }
        }
    }
}

Then in Main():

static void Main(string[] args)
{
     List<int> test = new List<int> { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
     GetData(test, 6);
     foreach (var item in Set)
     {
         Console.WriteLine("'t" + item.Key);
         foreach (var subitem in item.Value)
         {
             Console.WriteLine(subitem);
         }
     }
}