অন্য তালিকা আইডি থেকে একটি তালিকা সাজান


150

এই জাতীয় কিছু শনাক্তকারীদের সাথে আমার একটি তালিকা রয়েছে:

List<long> docIds = new List<long>() { 6, 1, 4, 7, 2 };

মোরোভার, আমার কাছে <T>আইটেমগুলির আরও একটি তালিকা রয়েছে , যা উপরে বর্ণিত আইডির দ্বারা প্রতিনিধিত্ব করা হয়েছে।

List<T> docs = GetDocsFromDb(...)

আমার উভয় সংগ্রহে একই ক্রম রাখা দরকার, যাতে আইটেমগুলি List<T>অবশ্যই প্রথমের তুলনায় একই অবস্থানে থাকতে হবে (সার্চ ইঞ্জিনের স্কোরিং কারণে)। এবং এই প্রক্রিয়াটি GetDocsFromDb()ফাংশনে করা যায় না ।

যদি প্রয়োজন হয় তবে দ্বিতীয় তালিকাটিকে অন্য কোনও কাঠামোর ( Dictionary<long, T>উদাহরণস্বরূপ) রূপান্তর করা সম্ভব , তবে আমি এটি পরিবর্তন না করাকে পছন্দ করব।

লিনকুইউয়ের সাথে "কিছু আইডির উপর নির্ভর করে" অরোডেনেশন করার কি কোনও সহজ এবং দক্ষ উপায় আছে?


আপনি কি নিশ্চিত যে প্রতিবারের docIdঠিক একবারে ঘটে যায় docs, কোন সম্পত্তি অধিষ্ঠিত Idহবে বা একটি নির্বাচক Func<T, long>প্রয়োজন হবে?
জোডরেল

প্রথম তালিকাটি কি "মাস্টার তালিকার" প্রতিনিধিত্ব করে? আরেকটি শব্দ, দ্বিতীয় তালিকাটি কি প্রথম তালিকার কোনও অংশ (বা সম্পূর্ণতা) উপস্থাপনের উপসেট হবে?
কোড

উত্তর:


332
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();

@ কাফ সাহেব কেন আমিও আপত্তি তুলেছি, ডকুমেন্ট আইডি সম্পত্তি জানার উপর নির্ভর করে না Id। এটি প্রশ্নে নির্দিষ্ট করা হয়নি।
জোডরেল

3
@ বোরজালেপেজ, একটি দ্রুত নোট। আপনি আপনার প্রশ্নে দক্ষতার কথা উল্লেখ করেছেন। IndexOfআপনার উদাহরণের জন্য নিখুঁতভাবে গ্রহণযোগ্য এবং সুন্দর এবং সাধারণ is আপনার কাছে প্রচুর ডেটা থাকলে আমার উত্তরটি আরও উপযুক্ত suited stackoverflow.com/questions/3663014/…
জোডরেল

2
পুনঃটুইট অনেক ধন্যবাদ; ঠিক আমি খুঁজছেন ছিল কি.
সিল্কফায়ার

3
ক্রমের তালিকায় আইড না থাকা
ডক্সে

4
বেশ অযোগ্য - সূচক সংগ্রহের প্রতিটি উপাদানগুলির জন্য সূচিপত্রকে ডাকা হচ্ছে এবং অর্ডারবাইকে উপাদানগুলি অর্ডার করতে হবে। @ জোডরেলের সমাধানটি আরও দ্রুত is
এসডিসি

25

যেহেতু আপনি নির্দিষ্ট করেন না T,

IEnumerable<T> OrderBySequence<T, TId>(
       this IEnumerable<T> source,
       IEnumerable<TId> order,
       Func<T, TId> idSelector)
{
    var lookup = source.ToDictionary(idSelector, t => t);
    foreach (var id in order)
    {
        yield return lookup[id];
    }
}

আপনি যা চান তার জেনেরিক এক্সটেনশন।

আপনি সম্ভবত এক্সটেনশনটি ব্যবহার করতে পারেন,

var orderDocs = docs.OrderBySequence(docIds, doc => doc.Id);

একটি নিরাপদ সংস্করণ হতে পারে

IEnumerable<T> OrderBySequence<T, TId>(
       this IEnumerable<T> source,
       IEnumerable<TId> order,
       Func<T, TId> idSelector)
{
    var lookup = source.ToLookup(idSelector, t => t);
    foreach (var id in order)
    {
        foreach (var t in lookup[id])
        {
           yield return t;
        }
    }
}

যা sourceঠিক যদি জিপ না করে তবে কাজ করবে order


আমি এই সমাধানটি ব্যবহার করেছি এবং এটি কার্যকর হয়েছে। কেবল এটিই, আমাকে পদ্ধতিটি স্থিতিশীল এবং শ্রেণি স্থির করতে হয়েছিল।
ভিনম

5

জোডরেলের উত্তর সবচেয়ে ভাল তবে আসলে তিনি পুনরায় প্রয়োগ করেছিলেন System.Linq.Enumerable.Join। যোগদানও লুকআপ ব্যবহার করে এবং উত্স ক্রম রাখে।

    docIds.Join(
      docs,
      i => i,
      d => d.Id,
      (i, d) => d);

এটি আমরা উত্তর খুঁজছি
ওরেস

2
এটি কেবল প্রমাণ করে যে জয়েন বুঝতে অসুবিধা হয় যেহেতু সকলেই সম্মত হন যে এটির পুনর্লিখন সহজ ছিল।
PRMan

-3

একটি সহজ পদ্ধতির ক্রম ক্রম দিয়ে জিপ করা হয়:

List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create)
               .OrderBy(x => x.Item2).Select(x => x.Item1).ToList();

কেন একটি জিপ পরে আদেশ?
জোডরেল

কারণ Zipপ্রতিটি সূচকে (একটি টুপলে) সংযুক্ত করে সংশ্লিষ্ট তালিকার একই অবস্থানে নথির সাথে। তারপরে অর্ডারবাই সূচক অংশ অনুসারে টিপলগুলি বাছাই করে এবং তারপরে নির্বাচন করুন এখন অর্ডার করা তালিকা থেকে আমাদের ডক্সটি খনন করে।
আলবিন সুন্নানবো

তবে, GetDocsFromDb এর ফলাফলটি আনর্ডারড হয়েছে যাতে আপনি Item1এমন টিউপস তৈরি করবেন যেখানে সম্পর্কিত নয় Item2
জোডরেল

1
আমি মনে করি এটি ইউপোন আইডি সম্পাদনা করার সূচীর পরিবর্তে ভুল ফলাফল আনবে।
মাইকেল লোগুতভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.