C# 连续正整数之和

C# 连续正整数之和,c#,linq,C#,Linq,我想对连续的正整数求和,从每个负值开始求和 输入: 输出: 我尝试了类似input.Wherex=>x>0.Sum;但这不起作用使用用于查找序列中连续项的,您可以在一行中执行此操作: var outSeq = input .ChunkBy(x => x >= 0 ? 1 : -1) .Where(g => g.Key > 0) .Select(g => g.Sum()); 这是ChunkBy代码,复制到这里是为了防止潜在的链接腐烂,注意,这是微软的作品

我想对连续的正整数求和,从每个负值开始求和

输入:

输出:

我尝试了类似input.Wherex=>x>0.Sum;但这不起作用

使用用于查找序列中连续项的,您可以在一行中执行此操作:

var outSeq = input
  .ChunkBy(x => x >= 0 ? 1 : -1)
  .Where(g => g.Key > 0)
  .Select(g => g.Sum());
这是ChunkBy代码,复制到这里是为了防止潜在的链接腐烂,注意,这是微软的作品,不是我自己的。。。有关原始来源和一些背景信息,请参见上面的链接:

public static class MyExtensions
{
    public static IEnumerable<IGrouping<TKey, TSource>> ChunkBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        return source.ChunkBy(keySelector, EqualityComparer<TKey>.Default);
    }

    public static IEnumerable<IGrouping<TKey, TSource>> ChunkBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
    {
        // Flag to signal end of source sequence. 
        const bool noMoreSourceElements = true;

        // Auto-generated iterator for the source array.        
        var enumerator = source.GetEnumerator();

        // Move to the first element in the source sequence. 
        if (!enumerator.MoveNext()) yield break;

        // Iterate through source sequence and create a copy of each Chunk. 
        // On each pass, the iterator advances to the first element of the next "Chunk" 
        // in the source sequence. This loop corresponds to the outer foreach loop that 
        // executes the query.
        Chunk<TKey, TSource> current = null;
        while (true)
        {
            // Get the key for the current Chunk. The source iterator will churn through 
            // the source sequence until it finds an element with a key that doesn't match. 
            var key = keySelector(enumerator.Current);

            // Make a new Chunk (group) object that initially has one GroupItem, which is a copy of the current source element.
            current = new Chunk<TKey, TSource>(key, enumerator, value => comparer.Equals(key, keySelector(value)));

            // Return the Chunk. A Chunk is an IGrouping<TKey,TSource>, which is the return value of the ChunkBy method. 
            // At this point the Chunk only has the first element in its source sequence. The remaining elements will be 
            // returned only when the client code foreach's over this chunk. See Chunk.GetEnumerator for more info. 
            yield return current;

            // Check to see whether (a) the chunk has made a copy of all its source elements or  
            // (b) the iterator has reached the end of the source sequence. If the caller uses an inner 
            // foreach loop to iterate the chunk items, and that loop ran to completion, 
            // then the Chunk.GetEnumerator method will already have made 
            // copies of all chunk items before we get here. If the Chunk.GetEnumerator loop did not 
            // enumerate all elements in the chunk, we need to do it here to avoid corrupting the iterator 
            // for clients that may be calling us on a separate thread. 
            if (current.CopyAllChunkElements() == noMoreSourceElements)
            {
                yield break;
            }
        }
    }

    // A Chunk is a contiguous group of one or more source elements that have the same key. A Chunk  
    // has a key and a list of ChunkItem objects, which are copies of the elements in the source sequence. 
    class Chunk<TKey, TSource> : IGrouping<TKey, TSource>
    {
        // INVARIANT: DoneCopyingChunk == true ||  
        //   (predicate != null && predicate(enumerator.Current) && current.Value == enumerator.Current) 

        // A Chunk has a linked list of ChunkItems, which represent the elements in the current chunk. Each ChunkItem 
        // has a reference to the next ChunkItem in the list. 
        class ChunkItem
        {
            public ChunkItem(TSource value)
            {
                Value = value;
            }
            public readonly TSource Value;
            public ChunkItem Next = null;
        }
        // The value that is used to determine matching elements 
        private readonly TKey key;

        // Stores a reference to the enumerator for the source sequence 
        private IEnumerator<TSource> enumerator;

        // A reference to the predicate that is used to compare keys. 
        private Func<TSource, bool> predicate;

        // Stores the contents of the first source element that 
        // belongs with this chunk. 
        private readonly ChunkItem head;

        // End of the list. It is repositioned each time a new 
        // ChunkItem is added. 
        private ChunkItem tail;

        // Flag to indicate the source iterator has reached the end of the source sequence. 
        internal bool isLastSourceElement = false;

        // Private object for thread syncronization 
        private object m_Lock;

        // REQUIRES: enumerator != null && predicate != null 
        public Chunk(TKey key, IEnumerator<TSource> enumerator, Func<TSource, bool> predicate)
        {
            this.key = key;
            this.enumerator = enumerator;
            this.predicate = predicate;

            // A Chunk always contains at least one element.
            head = new ChunkItem(enumerator.Current);

            // The end and beginning are the same until the list contains > 1 elements.
            tail = head;

            m_Lock = new object();
        }

        // Indicates that all chunk elements have been copied to the list of ChunkItems,  
        // and the source enumerator is either at the end, or else on an element with a new key. 
        // the tail of the linked list is set to null in the CopyNextChunkElement method if the 
        // key of the next element does not match the current chunk's key, or there are no more elements in the source. 
        private bool DoneCopyingChunk { get { return tail == null; } }

        // Adds one ChunkItem to the current group 
        // REQUIRES: !DoneCopyingChunk && lock(this) 
        private void CopyNextChunkElement()
        {
            // Try to advance the iterator on the source sequence. 
            // If MoveNext returns false we are at the end, and isLastSourceElement is set to true
            isLastSourceElement = !enumerator.MoveNext();

            // If we are (a) at the end of the source, or (b) at the end of the current chunk 
            // then null out the enumerator and predicate for reuse with the next chunk. 
            if (isLastSourceElement || !predicate(enumerator.Current))
            {
                enumerator = null;
                predicate = null;
            }
            else
            {
                tail.Next = new ChunkItem(enumerator.Current);
            }

            // tail will be null if we are at the end of the chunk elements 
            // This check is made in DoneCopyingChunk.
            tail = tail.Next;
        }

        // Called after the end of the last chunk was reached. It first checks whether 
        // there are more elements in the source sequence. If there are, it  
        // Returns true if enumerator for this chunk was exhausted. 
        internal bool CopyAllChunkElements()
        {
            while (true)
            {
                lock (m_Lock)
                {
                    if (DoneCopyingChunk)
                    {
                        // If isLastSourceElement is false, 
                        // it signals to the outer iterator 
                        // to continue iterating. 
                        return isLastSourceElement;
                    }
                    else
                    {
                        CopyNextChunkElement();
                    }
                }
            }
        }

        public TKey Key { get { return key; } }

        // Invoked by the inner foreach loop. This method stays just one step ahead 
        // of the client requests. It adds the next element of the chunk only after 
        // the clients requests the last element in the list so far. 
        public IEnumerator<TSource> GetEnumerator()
        {
            //Specify the initial element to enumerate.
            ChunkItem current = head;

            // There should always be at least one ChunkItem in a Chunk. 
            while (current != null)
            {
                // Yield the current item in the list. 
                yield return current.Value;

                // Copy the next item from the source sequence,  
                // if we are at the end of our local list. 
                lock (m_Lock)
                {
                    if (current == tail)
                    {
                        CopyNextChunkElement();
                    }
                }

                // Move to the next ChunkItem in the list.
                current = current.Next;
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

你需要自我循环。输入。其中x=>x>0.Sum;将所有正元素相加为一个和。您可以尝试以下方法:

int[] input = new int[] { 1, 2, 3, -1, 1, 3, -2, 3, 4 };

// a list is easier to use dynamic sizes
List<int> sums = new List<int>();

// the sum to the next negative number
int tmp_sum = 0;

// loop through
foreach(int _element in input)
{
    if(_element <= 0 )
    {
        if(tmp_sum > 0)
        {
            // negative element found, so save the sum if it is bigger than 0 
            sums.Add(tmp_sum);
            tmp_sum = 0;
        }
    }
    else
    {
        // keep summing up
        tmp_sum += _element;
    }    
}

//save the last one, if it is bigger than 0
if(tmp_sum > 0)
    sums.Add(tmp_sum);

// convert to an array
int[] result = sums.ToArray();

您有一个可执行的示例。

这里是一个使用LINQ的解决方案,不需要额外的扩展方法:

int[] list = new int[] { 1, 2, 3, 4, -1, 1, -2, 3, 4 };
int count = 0;

var result = list
    .GroupBy(n => n < 0 ? ++count : count)
    .Select(x => x.Sum(n => n > 0 ? n : 0));

@Sayse-OP说连续的正整数,1和3在-1之后是连续的:真的吗?对所有以3为一组出现的正整数求和?这不是OP要求的。这是非常脆弱的。假设输入列表更改为{1,2,3,4,-1,1,-2,3,4}?@spender,不确定它是如何脆弱的。在你的例子中,它会导致{6,5,7}一个OPs问题的提醒:我想对连续的正整数求和,从每个负值开始一个新的和。因此,从我上面给出的测试用例来看,我们不希望{10,1,7}吗?@spender,啊,我没有注意到它在每个负整数处启动一个新组。@spender,更新以纠正我对需求的误解。
int[] input = new int[] { 1, 2, 3, -1, 1, 3, -2, 3, 4 };

// a list is easier to use dynamic sizes
List<int> sums = new List<int>();

// the sum to the next negative number
int tmp_sum = 0;

// loop through
foreach(int _element in input)
{
    if(_element <= 0 )
    {
        if(tmp_sum > 0)
        {
            // negative element found, so save the sum if it is bigger than 0 
            sums.Add(tmp_sum);
            tmp_sum = 0;
        }
    }
    else
    {
        // keep summing up
        tmp_sum += _element;
    }    
}

//save the last one, if it is bigger than 0
if(tmp_sum > 0)
    sums.Add(tmp_sum);

// convert to an array
int[] result = sums.ToArray();
int[] list = new int[] { 1, 2, 3, 4, -1, 1, -2, 3, 4 };
int count = 0;

var result = list
    .GroupBy(n => n < 0 ? ++count : count)
    .Select(x => x.Sum(n => n > 0 ? n : 0));