লিনকিউ ব্যবহার করে ক্রমানুসারে শেষ উপাদান ছাড়া সমস্ত কীভাবে নেওয়া যায়?


131

ধরা যাক আমার একটি সিকোয়েন্স আছে।

IEnumerable<int> sequence = GetSequenceFromExpensiveSource();
// sequence now contains: 0,1,2,3,...,999999,1000000

ক্রমটি পাওয়া সস্তা নয় এবং গতিশীলভাবে উত্পন্ন হয় এবং আমি এটির মাধ্যমে একবারে পুনরাবৃত্তি করতে চাই।

আমি 0 - 999999 (অর্থাত্ শেষ উপাদান বাদে সবকিছু) পেতে চাই

আমি বুঝতে পারি যে আমি এরকম কিছু করতে পারি:

sequence.Take(sequence.Count() - 1);

তবে এর ফলশ্রুতিতে বৃহত ক্রমের উপরে দুটি গণনা আসে।

এমন একটি লিনকিউ নির্মাণ রয়েছে যা আমাকে করতে দেয়:

sequence.TakeAllButTheLastElement();

3
আপনাকে একটি ও (2 এন) সময় বা ও (গণনা) স্থান দক্ষতা অ্যালগরিদমের মধ্যে চয়ন করতে হবে, যেখানে পরবর্তীটির অভ্যন্তরীণ অ্যারেতে আইটেমগুলি সরিয়ে নেওয়াও প্রয়োজন।
ডায়কাম

1
দারিও, আপনি দয়া করে এমন কাউকে বুঝিয়ে বলবেন যে বড় অ-স্বীকৃতিতে নয়?
অ্যালেক্সন

আরও দেখুন এই ডুপ্লিকেট প্রশ্ন: stackoverflow.com/q/4166493/240733
stakx - আর অবদান

সংগ্রহটি তালিকায় রূপান্তর করে এবং তারপরে কল করে আমি এটি শেষ করেছিলাম sequenceList.RemoveAt(sequence.Count - 1);। আমার ক্ষেত্রে এটি গ্রহণযোগ্য কারণ সমস্ত লিনকিউ ম্যানিপুলেশনের পরে আমাকে এটিকে অ্যারে বা IReadOnlyCollectionযাইহোক রূপান্তর করতে হবে । আমি অবাক হই যে আপনার ব্যবহারের ক্ষেত্রে কী আপনি এমনকি ক্যাচিং বিবেচনা করেন না? আমি দেখতে পাচ্ছি এমনকি অনুমোদিত উত্তরটি কিছু ক্যাশে এত সহজ রূপান্তরিত করে Listযা আমার মতে খুব সহজ এবং খাটো।
পাভেলস আহমাদুলিনস

উত্তর:


64

আমি একটি লিনক সমাধান জানি না - তবে আপনি জেনারেটর (ফলন ফেরত) ব্যবহার করে খুব সহজেই অ্যালগরিদম কোড করতে পারেন।

public static IEnumerable<T> TakeAllButLast<T>(this IEnumerable<T> source) {
    var it = source.GetEnumerator();
    bool hasRemainingItems = false;
    bool isFirst = true;
    T item = default(T);

    do {
        hasRemainingItems = it.MoveNext();
        if (hasRemainingItems) {
            if (!isFirst) yield return item;
            item = it.Current;
            isFirst = false;
        }
    } while (hasRemainingItems);
}

static void Main(string[] args) {
    var Seq = Enumerable.Range(1, 10);

    Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
    Console.WriteLine(string.Join(", ", Seq.TakeAllButLast().Select(x => x.ToString()).ToArray()));
}

বা সর্বনিম্ন সমাধান হিসাবে সর্বশেষ এন আইটেমগুলি বাতিল করে (মন্তব্যগুলিতে প্রস্তাবিত একটি সারি ব্যবহার করে):

public static IEnumerable<T> SkipLastN<T>(this IEnumerable<T> source, int n) {
    var  it = source.GetEnumerator();
    bool hasRemainingItems = false;
    var  cache = new Queue<T>(n + 1);

    do {
        if (hasRemainingItems = it.MoveNext()) {
            cache.Enqueue(it.Current);
            if (cache.Count > n)
                yield return cache.Dequeue();
        }
    } while (hasRemainingItems);
}

static void Main(string[] args) {
    var Seq = Enumerable.Range(1, 4);

    Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
    Console.WriteLine(string.Join(", ", Seq.SkipLastN(3).Select(x => x.ToString()).ToArray()));
}

7
এখন আপনি চূড়ান্ত এন ব্যতীত সমস্ত নিতে সাধারণ করতে পারেন?
এরিক লিপার্ট

4
খুশী হলাম। একটি ছোট ত্রুটি; কিউয়ের আকারটি এন -1 করাতে হবে কারণ এটি কিউয়ের সর্বাধিক আকার।
এরিক লিপার্ট

রিশার্পার আপনার কোডটি বুঝতে পারে না ( শর্তসাপেক্ষ এক্সপ্রেশনতে অ্যাসাইনমেন্ট ) তবে আমি এটি পছন্দ করি +1
йый

44

আপনার নিজস্ব পদ্ধতি তৈরির বিকল্প হিসাবে এবং কোনও ক্ষেত্রে উপাদানগুলির অর্ডার গুরুত্বপূর্ণ নয়, পরবর্তীটি কাজ করবে:

var result = sequence.Reverse().Skip(1);

49
নোট করুন যে এর জন্য আপনার পুরো ক্রমটি সংরক্ষণ করার জন্য পর্যাপ্ত মেমরি থাকতে পারে এবং অবশ্যই বিপরীত ক্রমটি তৈরি করতে এবং একবার পুনরাবৃত্তি করার জন্য এটি পুরো ক্রমটি দু'বার পুনরুক্ত করে। আপনি এটি যতই টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো করে কাউন্ট সমাধানের চেয়ে এটির চেয়েও খারাপ এটি; এটি ধীরে ধীরে এবং আরও বেশি স্মৃতি গ্রহণ করে।
এরিক লিপার্ট

'বিপরীত' পদ্ধতিটি কীভাবে কাজ করে তা আমি জানি না, সুতরাং এটি কতটা মেমরি ব্যবহার করে তা সম্পর্কে আমি নিশ্চিত নই। তবে আমি দুটি পুনরাবৃত্তি সম্পর্কে একমত। এই পদ্ধতিটি বড় সংগ্রহগুলিতে ব্যবহার করা উচিত নয় বা যদি কোনও পারফরম্যান্স গুরুত্বপূর্ণ।
কামারে

5
ওয়েল, কিভাবে হবে আপনি বিপরীত বাস্তবায়ন? পুরো ক্রমটি সংরক্ষণ না করে এটি করার জন্য আপনি সাধারণভাবে কোনও উপায় বের করতে পারেন?
এরিক লিপার্ট

2
আমি এটি পছন্দ করি এবং এটি ক্রমটি দু'বার তৈরি না করার মানদণ্ড পূরণ করে।
অ্যামি বি

12
এবং অতিরিক্ত হিসাবে আপনি এটি পুরোপুরি equence.Reverse().Skip(1).Reverse()
পুনরুদ্ধার

42

কারণ আমি স্পষ্টভাবে কোনও ব্যবহারের ভক্ত নই Enumerator, তবে এখানে একটি বিকল্প রয়েছে। মনে রাখবেন যে ক্রমটি প্রকৃতপক্ষে গণনা না করা অবধি চেকগুলি পিছিয়ে দেওয়ার চেয়ে অবৈধ যুক্তিগুলিকে তাড়াতাড়ি ছড়িয়ে দেওয়ার জন্য মোড়কের পদ্ধতিগুলির প্রয়োজন।

public static IEnumerable<T> DropLast<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentNullException("source");

    return InternalDropLast(source);
}

private static IEnumerable<T> InternalDropLast<T>(IEnumerable<T> source)
{
    T buffer = default(T);
    bool buffered = false;

    foreach (T x in source)
    {
        if (buffered)
            yield return buffer;

        buffer = x;
        buffered = true;
    }
}

এরিক লিপার্টের পরামর্শ অনুসারে, এটি সহজেই আইটেমগুলিতে সাধারণীকরণ করে:

public static IEnumerable<T> DropLast<T>(this IEnumerable<T> source, int n)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (n < 0)
        throw new ArgumentOutOfRangeException("n", 
            "Argument n should be non-negative.");

    return InternalDropLast(source, n);
}

private static IEnumerable<T> InternalDropLast<T>(IEnumerable<T> source, int n)
{
    Queue<T> buffer = new Queue<T>(n + 1);

    foreach (T x in source)
    {
        buffer.Enqueue(x);

        if (buffer.Count == n + 1)
            yield return buffer.Dequeue();
    }
}

আমি এখন ফলনের পরে পরিবর্তে ফলনের আগে বাফার করি , যাতে কেসটির n == 0বিশেষ পরিচালনা করার প্রয়োজন না হয়।


প্রথম উদাহরণে, নির্ধারিত buffered=falseহওয়ার আগে অন্য কোনও ধারা স্থাপন করা সম্ভবত সর্বদা সামান্য দ্রুত হবে buffer। শর্তটি ইতিমধ্যে যাইহোক যাইহোক যাচাই করা হচ্ছে, তবে এটি bufferedপ্রতিটি সময় লুপের মাধ্যমে অপ্রয়োজনীয়ভাবে সেট করা এড়াতে পারে ।
জেমস

কেউ কি আমাকে এই বনাম বাছাইকৃত উত্তরগুলির উপকারিতা / ধারণা বলতে পারেন?
সিঞ্জাই

ইনপুট চেকের অভাব আছে এমন একটি পৃথক পদ্ধতিতে বাস্তবায়ন করার সুবিধা কী? এছাড়াও, আমি কেবল একক বাস্তবায়নটি বাদ দিয়ে একাধিক বাস্তবায়নকে একটি ডিফল্ট মান দেব give
jpmc26

@ jpmc26 একটি পৃথক পদ্ধতিতে চেক সহ, আপনি কল করার মুহুর্তে আপনি সত্যতাটি পেয়ে যাবেন DropLast। অন্যথায় বৈধতা তখনই ঘটে যখন আপনি প্রকৃতপক্ষে ক্রমটি অঙ্ক করবেন ( MoveNextফলাফলের প্রথম কলটিতে IEnumerator)। ডিবাগ করা মজাদার জিনিস নয় যখন IEnumerableএটিকে উত্পন্ন করা এবং প্রকৃতপক্ষে গণনার মধ্যে একটি স্বেচ্ছাসেবী কোড থাকতে পারে । আজকাল আমি এর InternalDropLastঅভ্যন্তরীণ ফাংশন হিসাবে DropLastলিখতাম, তবে 9 বছর আগে আমি এই কোডটি লেখার সময় সি # তে এই কার্যকারিতাটির অস্তিত্ব ছিল না।
জোরেেন

28

Enumerable.SkipLast(IEnumerable<TSource>, Int32).NET স্ট্যান্ডার্ড 2.1 এ পদ্ধতিটি যুক্ত করা হয়েছিল। এটি আপনি যা চান ঠিক তা করে।

IEnumerable<int> sequence = GetSequenceFromExpensiveSource();

var allExceptLast = sequence.SkipLast(1);

Https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skiplast থেকে

উত্স থেকে সংগৃহীত উত্স সংগ্রহের সর্বশেষ গণনা উপাদানগুলি সহ উপাদান থেকে উপাদানগুলিকে অন্তর্ভুক্ত করে এমন একটি নতুন গণনার সংগ্রহ সংগ্রহ করে।


2
এটি মোরলিংক
লেপারকন-এ

SkipLast এর জন্য +1। আমি সম্প্রতি নেট নেট ফ্রেমওয়ার্ক থেকে আসার পর থেকে এটি আমি জানতাম না এবং তারা সেখানে এটি যুক্ত করার জন্য মাথা ঘামায় না।
পিআরম্যান

12

ছাত্রলীগের কিছু নেই (বা আমি বিশ্বাস করি মোরলিঙ্ক) তবে আপনি নিজের সম্প্রসারণ পদ্ধতি তৈরি করতে পারেন।

public static IEnumerable<T> TakeAllButLast<T>(this IEnumerable<T> source)
{
    using (var enumerator = source.GetEnumerator())
        bool first = true;
        T prev;
        while(enumerator.MoveNext())
        {
            if (!first)
                yield return prev;
            first = false;
            prev = enumerator.Current;
        }
    }
}

এই কোডটি কাজ করবে না ... সম্ভবত হওয়া উচিত if (!first)এবং first = falseif এর বাইরে বেরিয়ে আসা উচিত।
কালেব

এই কোড বন্ধ দেখাচ্ছে। যুক্তি বলে মনে হচ্ছে ' prevপ্রথম পুনরাবৃত্তিতে অবিচ্ছিন্নিত ফিরিয়ে দিন এবং তার পরে চিরতরে লুপ'।
ফিল মিলার

কোডটিতে "সংকলন সময়" ত্রুটি রয়েছে বলে মনে হচ্ছে। আপনি এটি সংশোধন করতে চান হতে পারে। তবে হ্যাঁ, আমরা এমন একটি এক্সটেন্ডার লিখতে পারি যা একবারে পুনরাবৃত্তি করে এবং শেষ আইটেম ব্যতীত সমস্ত প্রদান করে।
মনিশ বাসন্তানী

@ কালেব: আপনি একেবারে ঠিক বলেছেন - আমি এটি সত্যই ভিড় করে লিখেছি! এখনই স্থির। @ অ্যাম্বি: এরম, আপনি কোন সংকলকটি ব্যবহার করছেন তা নিশ্চিত নন। আমার বাছাইয়ের কিছুই ছিল না। : পি
নলডোরিন

@ রবার্টস্কমিট ওফস, হ্যাঁ আমি usingএখন একটি বিবৃতি যোগ ।
নলডোরিন

7

এটি কার্যকর হবে যদি .NET ফ্রেমওয়ার্কটি এভাবে এক্সটেনশন পদ্ধতিতে প্রেরণ করা হত।

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count)
{
    var enumerator = source.GetEnumerator();
    var queue = new Queue<T>(count + 1);

    while (true)
    {
        if (!enumerator.MoveNext())
            break;
        queue.Enqueue(enumerator.Current);
        if (queue.Count > count)
            yield return queue.Dequeue();
    }
}

3

জোরেনের মার্জিত সমাধানের জন্য সামান্য বিস্তৃতি:

public static IEnumerable<T> Shrink<T>(this IEnumerable<T> source, int left, int right)
{
    int i = 0;
    var buffer = new Queue<T>(right + 1);

    foreach (T x in source)
    {
        if (i >= left) // Read past left many elements at the start
        {
            buffer.Enqueue(x);
            if (buffer.Count > right) // Build a buffer to drop right many elements at the end
                yield return buffer.Dequeue();    
        } 
        else i++;
    }
}
public static IEnumerable<T> WithoutLast<T>(this IEnumerable<T> source, int n = 1)
{
    return source.Shrink(0, n);
}
public static IEnumerable<T> WithoutFirst<T>(this IEnumerable<T> source, int n = 1)
{
    return source.Shrink(n, 0);
}

সর্বনিম্ন leftউপাদানগুলি যেখানে প্রথম অনেক উপাদান এবং একই সাথে ফেলে দেওয়া বাফারকে শেষের rightঅনেক উপাদানগুলি ফেলে দেওয়ার জন্য একটি সাধারণ গণনা এগিয়ে রাখে ।


3

আপনার নিজের এক্সটেনশানটি রোল করার সময় না থাকলে এখানে দ্রুততর উপায়:

var next = sequence.First();
sequence.Skip(1)
    .Select(s => 
    { 
        var selected = next;
        next = s;
        return selected;
    });

2

গৃহীত উত্তরের উপর সামান্য প্রকরণ, যা (আমার স্বাদের জন্য) কিছুটা সহজ is

    public static IEnumerable<T> AllButLast<T>(this IEnumerable<T> enumerable, int n = 1)
    {
        // for efficiency, handle degenerate n == 0 case separately 
        if (n == 0)
        {
            foreach (var item in enumerable)
                yield return item;
            yield break;
        }

        var queue = new Queue<T>(n);
        foreach (var item in enumerable)
        {
            if (queue.Count == n)
                yield return queue.Dequeue();

            queue.Enqueue(item);
        }
    }

2

আপনি যদি বেশিরভাগ ক্ষেত্রে আপনি এটি করতে পারেন এমন একটি Countবা Lengthতার একটি সংখ্যা পেতে পারেন তবে ঠিক justTake(n - 1)

অ্যারে সহ উদাহরণ

int[] arr = new int[] { 1, 2, 3, 4, 5 };
int[] sub = arr.Take(arr.Length - 1).ToArray();

সঙ্গে উদাহরণ IEnumerable<T>

IEnumerable<int> enu = Enumerable.Range(1, 100);
IEnumerable<int> sub = enu.Take(enu.Count() - 1);

প্রশ্নটি IEnumerables সম্পর্কে এবং আপনার সমাধানটি ওপি এড়াতে চেষ্টা করছে is আপনার কোডটির কার্যকারিতা প্রভাব রয়েছে।
নওফাল

1

কেন কেবল .ToList<type>()ক্রম অনুসারে নয়, তারপরে কল করুন এবং আপনি যেমনটি করেছেন ঠিক তেমন গ্রহণ করুন .. তবে যেহেতু এটি তালিকায় টানা হয়েছে, এটি দুবার ব্যয়বহুল গণনা করা উচিত নয়। রাইট?


1

এই সমস্যার জন্য আমি যে সমাধানটি ব্যবহার করি তা আরও বিস্তৃত।

আমার ব্যবহারের স্ট্যাটিক শ্রেণিতে একটি এক্সটেনশন পদ্ধতি রয়েছে MarkEndযা T-items ইন EndMarkedItem<T>-াইটেমগুলিতে রূপান্তর করে । প্রতিটি উপাদান অতিরিক্ত দিয়ে চিহ্নিত intকরা হয়, যা হয় 0 ; বা (বিশেষত একশেষে শেষ 3 টি আইটেমের প্রতি আগ্রহী) -3 , -2 , বা -1 সর্বশেষ 3 টি আইটেমের জন্য।

এটি নিজস্বভাবে দরকারী হতে পারে, উদাহরণস্বরূপ যখন আপনি foreachশেষ 2 ব্যতীত প্রতিটি উপাদান বাদে কমা দিয়ে একটি সহজ- লুপে একটি তালিকা তৈরি করতে চান , দ্বিতীয় থেকে শেষ আইটেমের পরে একটি সংমিশ্রণ শব্দ থাকে (যেমন " এবং " বা " বা ") এবং শেষ উপাদানটি পরে বিন্দু by

গত ছাড়া সমগ্র তালিকা জেনারেট করার জন্য এন আইটেম, এক্সটেনশন পদ্ধতি ButLastকেবল উপর iterates EndMarkedItem<T>গুলি যখন EndMark == 0

আপনি যদি নির্দিষ্ট না করে থাকেন তবে tailLengthকেবলমাত্র শেষ আইটেমটি চিহ্নিত (ইন MarkEnd()) বা ড্রপ (ইন ButLast()) হয়।

অন্যান্য সমাধানগুলির মতো, এটি বাফার করে কাজ করে।

using System;
using System.Collections.Generic;
using System.Linq;

namespace Adhemar.Util.Linq {

    public struct EndMarkedItem<T> {
        public T Item { get; private set; }
        public int EndMark { get; private set; }

        public EndMarkedItem(T item, int endMark) : this() {
            Item = item;
            EndMark = endMark;
        }
    }

    public static class TailEnumerables {

        public static IEnumerable<T> ButLast<T>(this IEnumerable<T> ts) {
            return ts.ButLast(1);
        }

        public static IEnumerable<T> ButLast<T>(this IEnumerable<T> ts, int tailLength) {
            return ts.MarkEnd(tailLength).TakeWhile(te => te.EndMark == 0).Select(te => te.Item);
        }

        public static IEnumerable<EndMarkedItem<T>> MarkEnd<T>(this IEnumerable<T> ts) {
            return ts.MarkEnd(1);
        }

        public static IEnumerable<EndMarkedItem<T>> MarkEnd<T>(this IEnumerable<T> ts, int tailLength) {
            if (tailLength < 0) {
                throw new ArgumentOutOfRangeException("tailLength");
            }
            else if (tailLength == 0) {
                foreach (var t in ts) {
                    yield return new EndMarkedItem<T>(t, 0);
                }
            }
            else {
                var buffer = new T[tailLength];
                var index = -buffer.Length;
                foreach (var t in ts) {
                    if (index < 0) {
                        buffer[buffer.Length + index] = t;
                        index++;
                    }
                    else {
                        yield return new EndMarkedItem<T>(buffer[index], 0);
                        buffer[index] = t;
                        index++;
                        if (index == buffer.Length) {
                            index = 0;
                        }
                    }
                }
                if (index >= 0) {
                    for (var i = index; i < buffer.Length; i++) {
                        yield return new EndMarkedItem<T>(buffer[i], i - buffer.Length - index);
                    }
                    for (var j = 0; j < index; j++) {
                        yield return new EndMarkedItem<T>(buffer[j], j - index);
                    }
                }
                else {
                    for (var k = 0; k < buffer.Length + index; k++) {
                        yield return new EndMarkedItem<T>(buffer[k], k - buffer.Length - index);
                    }
                }
            }    
        }
    }
}

1
    public static IEnumerable<T> NoLast<T> (this IEnumerable<T> items) {
        if (items != null) {
            var e = items.GetEnumerator();
            if (e.MoveNext ()) {
                T head = e.Current;
                while (e.MoveNext ()) {
                    yield return head; ;
                    head = e.Current;
                }
            }
        }
    }

1

আমি মনে করি না যে এটি এর চেয়ে বেশি সাফল্য পেতে পারে - এছাড়াও এটির নিষ্পত্তি নিশ্চিত করে IEnumerator<T>:

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
    using (var it = source.GetEnumerator())
    {
        if (it.MoveNext())
        {
            var item = it.Current;
            while (it.MoveNext())
            {
                yield return item;
                item = it.Current;
            }
        }
    }
}

সম্পাদনা করুন: এই উত্তরটির সাথে প্রযুক্তিগতভাবে অভিন্ন ।


1

সি # 8.0 এর সাহায্যে আপনি এর জন্য ব্যাপ্তি এবং সূচকগুলি ব্যবহার করতে পারেন ।

var allButLast = sequence[..^1];

ডিফল্ট সি # 8.0 এর জন্য। নেট কোর 3.0 বা। নেট স্ট্যান্ডার্ড 2.1 (বা তারপরের) প্রয়োজন। পুরানো প্রয়োগগুলির সাথে ব্যবহার করতে এই থ্রেডটি পরীক্ষা করুন ।


0

আপনি লিখতে পারেন:

var list = xyz.Select(x=>x.Id).ToList();
list.RemoveAt(list.Count - 1);

0

এটি একটি সাধারণ এবং IMHO মার্জিত সমাধান যা সমস্ত ক্ষেত্রে সঠিকভাবে পরিচালনা করবে:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        IEnumerable<int> r = Enumerable.Range(1, 20);
        foreach (int i in r.AllButLast(3))
            Console.WriteLine(i);

        Console.ReadKey();
    }
}

public static class LinqExt
{
    public static IEnumerable<T> AllButLast<T>(this IEnumerable<T> enumerable, int n = 1)
    {
        using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
        {
            Queue<T> queue = new Queue<T>(n);

            for (int i = 0; i < n && enumerator.MoveNext(); i++)
                queue.Enqueue(enumerator.Current);

            while (enumerator.MoveNext())
            {
                queue.Enqueue(enumerator.Current);
                yield return queue.Dequeue();
            }
        }
    }
}

-1

আমার চিরাচরিত IEnumerableপদ্ধতি:

/// <summary>
/// Skips first element of an IEnumerable
/// </summary>
/// <typeparam name="U">Enumerable type</typeparam>
/// <param name="models">The enumerable</param>
/// <returns>IEnumerable of type skipping first element</returns>
private IEnumerable<U> SkipFirstEnumerable<U>(IEnumerable<U> models)
{
    using (var e = models.GetEnumerator())
    {
        if (!e.MoveNext()) return;
        for (;e.MoveNext();) yield return e.Current;
        yield return e.Current;
    }
}

/// <summary>
/// Skips last element of an IEnumerable
/// </summary>
/// <typeparam name="U">Enumerable type</typeparam>
/// <param name="models">The enumerable</param>
/// <returns>IEnumerable of type skipping last element</returns>
private IEnumerable<U> SkipLastEnumerable<U>(IEnumerable<U> models)
{
    using (var e = models.GetEnumerator())
    {
        if (!e.MoveNext()) return;
        yield return e.Current;
        for (;e.MoveNext();) yield return e.Current;
    }
}

আপনার স্কিপলাস্টআনামেবল প্রচলিত হতে পারে তবে এটি নষ্ট হয়েছে। এটি যে প্রথম উপাদানটি ফেরত দেয় তা সর্বদা একটি অপরিজ্ঞাত ইউ - এমনকি যখন "মডেলগুলি" এর 1 উপাদান থাকে। পরবর্তী ক্ষেত্রে, আমি একটি ফাঁকা ফলাফল আশা করব।
রবার্ট শ্মিড্ট

এছাড়াও, আইনিমরেটর <T> আইডিজিপোজেবল।
রবার্ট শ্মিড্ট

সত্য / লক্ষনীয়। ধন্যবাদ.
চিবুয়েজ ওপাটা

-1

একটি সহজ উপায় হ'ল আপনি যে আইটেমগুলি এড়িয়ে যেতে চান কেবল তার সংখ্যা বাকি না হওয়া পর্যন্ত কেবল একটি সারি এবং ডীকিতে রূপান্তর করা।

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
    var queue = new Queue<T>(source);

    while (queue.Count() > n)
    {
        yield return queue.Dequeue();
    }
}

পরিচিত সংখ্যক আইটেম নেওয়ার জন্য টেক ব্যবহার রয়েছে। এবং যথেষ্ট পরিমাণে গণনার জন্য সারি ভয়াবহ।
সিনাতর

-2

হতে পারে:

var allBuLast = sequence.TakeWhile(e => e != sequence.Last());

আমার ধারণা এটি ডি "হেইথ" এর মতো হওয়া উচিত তবে অর্ডার (?) সংরক্ষণ করা উচিত।


3
এটি এটি করার একটি খুব অদক্ষ উপায়। সিক্যুয়েন্স মূল্যায়নের জন্য। সর্বশেষ () এটিকে ক্রমের প্রতিটি উপাদানটির জন্য এটি করে পুরো ক্রমটি অতিক্রম করতে হবে। O (n ^ 2) দক্ষতা।
মাইক

তুমি ঠিক. আমি এই এক্সডিটি লেখার সময় আমি কী ভাবছিলাম তা জানি না। যাইহোক, আপনি কি নিশ্চিত যে শেষ () পুরো ক্রমটি অতিক্রম করবে? আইইনুমারেবল (যেমন অ্যারে) এর কিছু বাস্তবায়নের জন্য, এটি ও (1) হওয়া উচিত। আমি তালিকার প্রয়োগটি যাচাই করিনি, তবে এটিতে একটি "বিপরীত" পুনরুক্তিও থাকতে পারে, শেষ উপাদানটি থেকে শুরু করে, যা ও (1) গ্রহণ করে। এছাড়াও, আপনার বিবেচনা করা উচিত যে ও (এন) = ও (2 এন), অন্তত প্রযুক্তিগতভাবে বলছেন। অতএব, যদি এই অ্যাপ্লিকেশনগুলি আপনার অ্যাপ্লিকেশনগুলির পারফরম্যান্সের জন্য একেবারে সমালোচক না হয় তবে আমি আরও স্পষ্টতর সিকোয়েন্সের সাথে লেগে থাকব T (সিকোয়েন্স। অ্যাকাউন্ট () - 1)।
গিলারমো আরেস

@ মাইক আমি আপনার সাথে সাথী, সিক্যুয়েন্সের সাথে একমত নই L সর্বশেষ () হ'ল (1) যাতে এটি পুরো ক্রমটি অতিক্রম করার প্রয়োজন না হয়। stackoverflow.com/a/1377895/812598
GoRoS

1
@ গোরোস, যদি কেবল সিকোয়েনশন আইকোলিকেশন / আইলিস্ট প্রয়োগ করে বা অ্যারে হয় তবে এটি কেবল ও (1) থাকে। অন্যান্য সমস্ত সিকোয়েন্সগুলি হ'ল (এন)। আমার প্রশ্নে, আমি ধরে নিই না যে ও (1) উত্সগুলির মধ্যে একটি
মাইক 20

3
ক্রম বিভিন্ন আইটেম থাকতে পারে সন্তুষ্ট এই অবস্থা ই == sequence.Last (), উদাহরণস্বরূপ নতুন [] {1, 1, 1, 1} জন্য
সের্গেই Shandar

-2

গতি যদি প্রয়োজনীয়তা হয় তবে কোডটি লিনাকের মতো সাবলীল দেখায় না তবুও এই পুরাতন স্কুলটি দ্রুততম হওয়া উচিত।

int[] newSequence = int[sequence.Length - 1];
for (int x = 0; x < sequence.Length - 1; x++)
{
    newSequence[x] = sequence[x];
}

এটির জন্য একটি নির্দিষ্ট দৈর্ঘ্য এবং সূচিযুক্ত আইটেম রয়েছে তাই এটি ক্রমটি একটি অ্যারে প্রয়োজন।


2
আপনি এমন একটি IEnumerable নিয়ে কাজ করছেন যা কোনও সূচকের মাধ্যমে উপাদানগুলিতে অ্যাক্সেসের অনুমতি দেয় না। আপনার সমাধান কাজ করে না। ধরে নিলে আপনি এটি ঠিকঠাক করেছেন, দৈর্ঘ্য নির্ধারণের জন্য ক্রমটি অতিক্রম করতে হবে, দৈর্ঘ্যের এন -1 এর অ্যারে বরাদ্দ করে সমস্ত উপাদানকে অনুলিপি করতে হবে। - 1. 2n-1 অপারেশন এবং (2n-1) * (4 বা 8 বাইট) মেমরি। তাও দ্রুত নয়।
তারিক

-4

আমি সম্ভবত এরকম কিছু করব:

sequence.Where(x => x != sequence.LastOrDefault())

এটি চেক সহ একটি পুনরাবৃত্তি যা এটি প্রতিবারের জন্য শেষ নয়।


3
দুটি কারণ এটি করা ভাল জিনিস নয়। 1) .লাস্টঅর্ডার ডিফল্ট () এর পুরো ক্রমটি পুনরাবৃত্তি করা প্রয়োজন এবং এটি ক্রমের প্রতিটি উপাদানটির জন্য বলা হয়েছে (যেখানে (যেখানে))। 2) যদি ক্রমটি [1,2,1,2,1,2] হয় এবং আপনি আপনার কৌশলটি ব্যবহার করেন তবে আপনাকে [1,1,1] রেখে দেওয়া হবে be
মাইক 13
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.