العثور على مزيج من اثنين من العناصر التي لم ينظر إليها معا (LINQ, SQL أو C#)

StackOverflow https://stackoverflow.com/questions/601134

سؤال

لدي صفحة تعرض اثنين من الكائنات ومن ثم يختار المستخدم أحد من هؤلاء.لقد سجل تفضيل الجمع في قاعدة بيانات MSSQL و في نهاية المطاف تخزين البيانات مثل هذا:

UserId=1, BetterObjectId=1, WorseObjectId=2

الآن أود أن تجنب تبين أن مجموعة من الكائنات (1,2 / 2,1) من أي وقت مضى مرة أخرى.

كيف يمكنني إنشاء تركيبات عشوائية لتظهر للمستخدم باستثناء سابقا ينظر إلى مجموعات ؟

هذا يبدو أنه ينبغي أن يكون حقا مسألة واضحة ولكن مثل معظم المبرمجين أنا قصيرة على النوم والقهوة حتى مساعدتكم هو محل تقدير كبير :-)

على جدا من السذاجة النهج هو شيء من هذا القبيل (و كل ما يدعو إلى هذه الوظيفة يجب أن تكون ملفوفة في تحقق لمعرفة ما إذا كان المستخدم لديه بالفعل تصنيف عدة مرات كما nCr حيث n هو عدد العناصر و r 2):

public List<Item> GetTwoRandomItems(int userId)
{
    Item i = null, i2 = null;
    List<Item> r = null;

    while (i == null || i2 == null)
    {
        r = GetTwoRandomItemsRaw();
        i = r[0];
        i2 = r[1];
        if (GetRating(i.Id, i2.Id, userId) != null) /* Checks if viewed */
        {
            i = null;
            i2 = null;
        }
    }
    return r;
}

private List<Item> GetTwoRandomItemsRaw()
{
    return Items.ToList().OrderBy(i => Guid.NewGuid()).Take(2).ToList();
}

التعديلات

باستخدام بعض SQL يمكنني إنشاء قائمة من كافة العناصر التي ليست كاملة (أيهناك مزيج يشمل هذا البند أن المستخدم لم ير) ولكن لا أعتقد أنه مفيد بشكل خاص.

أنا أيضا أستطيع أن أتخيل توليد كل تركيبة ممكنة وإزالة بالفعل ينظر إليه منها قبل اختيار 2 البنود عشوائية ولكن هذا هو آخر رهيب الحل.

إمكانية (الذاكرة المكثفة كبيرة n) هو لتوليد جميع التوليفات الممكنة وتخزين combinationId في التصنيف.ثم أنا يمكن أن مجرد القيام حدد جميع مجموعات حيث combinationId ليس في (حدد combinationId من التقييم حيث userId=x) مع بعض التغييرات تعكس متماثل العلاقة من تركيبات.

هل كانت مفيدة؟

المحلول

Table Item: ItemId
Table Rating: UserId, ItemId1, ItemId2, WinnerId

إذا كنت تحتاج إلى أن ItemId1 < ItemId2 في جدول الترتيب, لديك فقط للتحقق من جدول تصنيف مرة واحدة.

var pair = db.Items.Join(db.Items,
  i1 => i1.ItemId,
  i2 => i2.ItemId,
  (i1, i2) => new {i1, i2}
)  //produce all pairs
.Where(x => x.i1.ItemId < x.i2.ItemId) //filter diagonal to unique pairs
.Where(x => 
  !db.Ratings
  .Where(r => r.UserId == userId
    && r.ItemId1 == x.i1.ItemId
    && r.ItemId2 == x.i2.ItemId)
  .Any() //not any ratings for this user and pair
)
.OrderBy(x => db.GetNewId()) //in-database random ordering
.First();  // just give me the first one

return new List<Item>() {pair.i1, pair.i2 };

هنا بلوق عن الحصول على "عشوائية" ترجمت إلى قاعدة البيانات.

نصائح أخرى

حل واحد هو هذا:

SELECT TOP 1 i.id item1, i2.id item2 from item i, item i2 
WHERE i.id <> i2.id 
AND (SELECT COUNT(*) FROM Rating WHERE userId=@userId AND FK_ItemBetter=i.id AND FK_ItemWorse=i2.id) = 0
AND (SELECT COUNT(*) FROM Rating WHERE userId=@userId AND FK_ItemBetter=i2.id AND FK_ItemWorse=i.id) = 0
ORDER BY NEWID()

لم أكن على علم عبر الانضمام طريقة مجرد سرد العديد من الجداول من قبل.

على افتراض أن قائمة العناصر المتاحة في قاعدة البيانات ، وأود أن التعامل مع هذه المشكلة تماما في قاعدة البيانات.كنت ضرب قاعدة بيانات بالفعل ، بغض النظر عن ما ، فلماذا لا تحصل عليه القيام به هناك ؟

ماذا عن وضع كافة الكائنات في طابور أو كومة, ثم بوب 2 و 2 حتى وهي فارغة ؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top