亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何根據對象的排序方式推斷對象的屬性?

如何根據對象的排序方式推斷對象的屬性?

揚帆大魚 2022-12-02 15:43:40
如果你運行下面的代碼片段,它會生成一個隨機的人列表,每個人都有一個獨特的orig屬性,你可以假裝這是他們到達機場的排隊順序(請多多包涵)。船長不公平,不讓人們按照他們到達的順序坐在相應的座位上。他更喜歡一些名字而不是其他名字,并且同樣喜歡一些名字。他的偏好由prefs對象說明。 Bob, Sue, 和Sal是他最喜歡的名字,但他同樣喜歡它們。 Ian并且Sam是他最不喜歡的,但他同樣不喜歡他們。所以這個不公平的船長根據他對他們名字的喜愛程度來招待他們。這意味著人員列表首先按照他們到達的順序排序,然后根據船長對他們名字的偏好再次排序。當您運行代碼片段時,它會生成一個對象列表,每個對象都只有一個name和orig(原始順序)屬性,并按上述方式排序。假裝船長的喜好是未知的。如果你生成一個足夠長的列表,或者一個足夠短的列表,你應該能夠推斷出這個prefs對象。僅給出列表,如何推斷prefs對象?我需要一個基于許多短列表的解決方案,而不是基于一個非常長的列表的解決方案。const prefs = {  Bob: { pref: 1 },  Sue: { pref: 1 },  Sal: { pref: 1 },  Jim: { pref: 2 },  Jon: { pref: 2 },  Lyn: { pref: 2 },  Ian: { pref: 3 },  Sam: { pref: 3 }};const names = Object.keys(prefs);const randomName = () => names[~~(Math.random() * names.length)];const list = new Array(5).fill().map((_, orig) => {  const name = randomName();  return { name, orig };}).sort((a, b) => prefs[a.name].pref > prefs[b.name].pref ? 1 : -1);console.log(list);這不是我的實際問題,但我希望這個簡化版本很容易理解。如果我能解決這個問題,那么我就能解決我真正的問題。
查看完整描述

3 回答

?
猛跑小豬

TA貢獻1858條經驗 獲得超8個贊

這是我的嘗試...在 generateList 之外我無權訪問prefs對象或pref值,我只獲得隨機名稱列表,然后嘗試對列表進行逆向工程:


let generateList = () => {

  const prefs = {

    Bob: { pref: 1 },

    Sue: { pref: 1 },

    Sal: { pref: 1 },

    Jim: { pref: 2 },

    Jon: { pref: 2 },

    Lyn: { pref: 2 },

    Ian: { pref: 3 },

    Sam: { pref: 3 }

  };


  const names = Object.keys(prefs);

  const randomName = () => names[~~(Math.random() * names.length)];


  const list = new Array(5).fill().map((_, orig) => {

    const name = randomName();

    return { name, orig };

  }).sort((a, b) => prefs[a.name].pref > prefs[b.name].pref ? 1 : -1);

  return list;

}


const lists = [];

for (let i = 0; i < 10000; i++) {

    lists.push(generateList())

}


let guess = {};

lists.forEach((list) => {

    list.forEach((item, index) => {

        guess[item.name] = (guess[item.name] || 0) + (list.length - index);

    });

});


// now we get the minimum

const min = Math.min(...Object.values(guess))

const max = Math.max(...Object.values(guess))

const offset = Math.round(max/min) + 1;


// now we guess the key order (as best we can), and set the pref

guess = Object.fromEntries(Object.entries(guess).map((item) => {

    item[1] = { pref: offset - Math.round(item[1]/min) };

    return item;

}).sort((a,b) => a[1].pref - b[1].pref));


console.log(guess)


查看完整回答
反對 回復 2022-12-02
?
陪伴而非守候

TA貢獻1757條經驗 獲得超8個贊

您可以只計算某個名稱的索引。結果,您得到一些代表船長偏好的組。


function generateSet() {

    const

        prefs = { Bob: { pref: 1 }, Sue: { pref: 1 }, Sal: { pref: 1 }, Jim: { pref: 2 }, Jon: { pref: 2 }, Lyn: { pref: 2 }, Ian: { pref: 3 }, Sam: { pref: 3 } },

        names = Object.keys(prefs),

        randomName = () => names[~~(Math.random() * names.length)];

    return Array

            .from({ length: 5 }, (_, orig) => ({ name: randomName(), orig }))

            .sort((a, b) => prefs[a.name].pref - prefs[b.name].pref);

}


function count(n) {

    const result = {};

    for (let i = 0; i < n; i++) {

        generateSet().forEach(({ name }, i) => result[name] = (result[name] || 0) + i);

    }

    return result;


console.log(count(10000));


查看完整回答
反對 回復 2022-12-02
?
白衣染霜花

TA貢獻1796條經驗 獲得超10個贊

這是我自己對我的問題的回答。它的工作原理是為每個人提供一個包含所有inferiors和的列表superiors。Aninferior將是在列表中出現在他們之上的人,但具有更大的orig. 唯一可能發生這種情況的方法是船長更喜歡他們。反之亦然superiors。


然后任何同時存在于someoneinferiors和superiorssomeone 列表中的人都會從這些列表中刪除并放入equals列表中,這意味著船長已經為他們分配了完全相同的偏好,因為這是他們可能同時出現的唯一方式 an inferiorand superior。


然后根據列表的長度對人們進行排名superiors;沒有superiors的人在頂部。擁有最多superiors的人位于底部。


然后這些equals組用于重建prefs對象(所有共享相同equals組的人都在同一組中)。


const intersect = (a, b) => {

  return new Set([...a].filter(x => b.has(x)));

}


const setsEqual = (a, b) => [...a].sort().toString() == [...b].sort().toString();


const prefs = {

  Bob: { pref: 1 },

  Sue: { pref: 1 },

  Sal: { pref: 1 },

  Jim: { pref: 2 },

  Jon: { pref: 2 },

  Lyn: { pref: 2 },

  Ian: { pref: 3 },

  Sam: { pref: 3 }

};


const names = Object.keys(prefs);

const randomName = () => names[~~(Math.random() * names.length)];

const randomList = () => new Array(5).fill().map((_, orig) => {

  const name = randomName();

  return { name, orig };

}).sort((a, b) => prefs[a.name].pref > prefs[b.name].pref ? 1 : -1);


const people = {};


for (let i = 0; i < 100; i++) {

  const list = randomList();

  list.forEach(({ name }) => !people[name] && (people[name] = {

    superiors: new Set(), inferiors: new Set()

  }));

  list.forEach(({ name, orig }, yourPos) => {

    const superiors = people[name].superiors;

    const inferiors = people[name].inferiors;

    list.forEach((person, theirPos) => {

      if (person.name == name) return;

      if (theirPos < yourPos && person.orig > orig) {

        superiors.add(person.name);

      }

      if (theirPos > yourPos && person.orig < orig) {

        inferiors.add(person.name);

      }

    });

  });

}


Object.entries(people).forEach(([name, { superiors, inferiors }]) => {

  const intersection = intersect(superiors, inferiors);

  for (const elem of intersection) {

    superiors.delete(elem);

    inferiors.delete(elem);

  }

});



Object.entries(people).forEach(([yourName, person]) => {

  Object.entries(people).forEach(([theirName, other]) => {

    const yourInferiors = person.inferiors;

    const yourSuperiors = person.superiors;


    const theirInferiors = other.inferiors;

    const theirSuperiors = other.superiors;


    if (setsEqual(yourInferiors, theirInferiors) && setsEqual(yourSuperiors, theirSuperiors)) {

      person.equals = person.equals || new Set();

      other.equals = other.equals || new Set();


      person.equals.add(theirName);

      other.equals.add(yourName);


      person.equals.add(yourName);

      other.equals.add(theirName);

    }

  });

});


const rankedPeople = Object.entries(people).sort(([, a], [, b]) => {

  return a.superiors.size > b.superiors.size ? 1 : -1;

}).map(([name, { equals }]) => {

  return { name, equals: [...equals].sort().toString() };

});


const groups = [...new Set(rankedPeople.map(({ equals }) => equals))]

  .map((group, pref) => ({ pref: pref + 1, group: group.split(',') }));


const deduction = {};


groups.forEach(({ pref, group }) => {

  group.forEach(name => {

    deduction[name] = pref;

  });

});


console.log(deduction);


目前,這是唯一可靠地解決僅100包含 length 列表的問題的答案5。事實上,只有一半的數量是相當可靠的。


此外,此解決方案不會混淆與其他人有關系的人;例如,如果 Bob 永遠不會和 Ian 一起出現,這只會阻止正確的分組,但不會導致 Bob 和 Ian 彼此之間出現混亂。


其他答案確實存在此缺陷。


查看完整回答
反對 回復 2022-12-02
  • 3 回答
  • 0 關注
  • 170 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號