簡體   English   中英

生成唯一的 id 對

[英]Generate unique ids pairs

我正在嘗試生成所有可能的唯一 ID 對。 目前我正試圖用兩個這樣的方法來實現它:

private prepareNewList(userIds: number[], existedPartnerList: string[]) {
    const newPartnerList = [];
    let usedUsersIds = [];

    for (let i = 0; i < userIds.length - 1; i++) {
      for (let j = i + 1; j < userIds.length; j++) {
        if (usedUsersIds.includes(userIds[i])) {
          continue;
        }

        const pair = ${userIds[i]}-${userIds[j]};
        const reversedPair = ${userIds[j]}-${userIds[i]};

        if (
          !existedPartnerList.includes(pair) &&
          !existedPartnerList.includes(reversedPair)
        ) {
          newPartnerList.push(pair);
          usedUsersIds.push(userIds[i], userIds[j]);

          break;
        }
      }
    }

    usedUsersIds = [];

    for (let i = userIds.length - 1; i > 0; i--) {
      for (let j = i - 1; j >= 0; j--) {
        if (usedUsersIds.includes(userIds[j])) {
          continue;
        }

        const pair = ${userIds[i]}-${userIds[j]};
        const reversedPair = ${userIds[j]}-${userIds[i]};

        if (
          !existedPartnerList.includes(pair) &&
          !existedPartnerList.includes(reversedPair) &&
          !newPartnerList.includes(pair) &&
          !newPartnerList.includes(reversedPair)
        ) {
          newPartnerList.push(pair);
          usedUsersIds.push(userIds[i], userIds[j]);

          break;
        }
      }
    }

    return this.filterPairs(newPartnerList);
  }

private filterPairs(pairs: string[]): string[] {
    const usedIds = [];
    const pairsToRemove = [];
    pairs = pairs.sort(() => Math.random() - 0.5);

    for (let i = 0; i < pairs.length; i++) {
      const parsedPair = pairs[i].split('-');

      if (parsedPair.some((id) => usedIds.includes(id))) {
        pairsToRemove.push(pairs[i]);
      }

      usedIds.push(...parsedPair);
    }

    return pairs.filter((item) => !pairsToRemove.includes(item));
  }

但它不能正常工作。 當我第一次運行腳本時,我得到['1-2', '3-4', '5-6', '6-4', '5-3', '4-2', '3-1']來自第一種方法和[ '1-2', '3-4', '5-6' ]過濾后,這是正確的(例如,來自 '6-4' 對的數字已經被用於“3-4”和“5-6”)。

當我第二次運行腳本時,我首先得到[ '1-3', '2-3', '4-5', '6-4', '5-3', '4-2' ]過濾后的方法和[ '1-3', '4-5' ] ,這是不正確的,因為還剩下一對[ '6-2' ][ '2-6' ]

所以我的方法並不像我期望的那樣工作。 我應該怎么做才能讓它發揮作用?

編輯 1:

我想每個月運行這個腳本來生成獨特的用戶對。 例如,本月我創建了“用戶 1-用戶 2”對。 所以在這個月我不能再使用用戶 1 和用戶 2,也不能永遠使用“用​​戶 1-用戶 2”對

編輯2:

也許我解釋不正確或不太准確。 每個月我都必須生成獨特的用戶對。 比如我有6個用戶(總有偶數),一開始我可以隨意生成,因為數據庫中的表是空的。 例如:1-2、3-4、5-6。 下個月我再次運行腳本,假設用戶數量沒有改變,現有的對 (1-2, 3-4, 5-6) 取自基礎,並基於這些現有的對我必須創建不會重復的新的(例如 1-4、2-6、3-5)。 因此,每個月都會增加 + 用戶,因此收益會增加。

取2(不可重復使用)

如果我正確理解了更新的要求,那么像這樣的遞歸函數怎么樣?

function generatePairs(ids) {
  const uniqueIds = Array.from(new Set(ids));
  const results = [];
  function generateNext(idBag, pairs = []) {
    const [a, ...rest] = idBag;
    rest.forEach((b) => {
      const newPairs = [...pairs, [a, b]];
      const next = rest.filter((e) => e !== b);
      if (next.length >= 2) {
        generateNext(next, newPairs);
      } else {
        results.push({ pairs: newPairs, rest: next });
      }
    });
  }
  generateNext(uniqueIds);
  return results;
}

對於偶數個用戶,例如

generatePairs(["John", "Mary", "Anne", "Zalgo", "Kenny", "Ben"]).forEach((result) => {
  console.log(result.pairs, result.rest);
});

結果是

[ [ 'John', 'Mary' ], [ 'Anne', 'Zalgo' ], [ 'Kenny', 'Ben' ] ] []
[ [ 'John', 'Mary' ], [ 'Anne', 'Kenny' ], [ 'Zalgo', 'Ben' ] ] []
[ [ 'John', 'Mary' ], [ 'Anne', 'Ben' ], [ 'Zalgo', 'Kenny' ] ] []
[ [ 'John', 'Anne' ], [ 'Mary', 'Zalgo' ], [ 'Kenny', 'Ben' ] ] []
[ [ 'John', 'Anne' ], [ 'Mary', 'Kenny' ], [ 'Zalgo', 'Ben' ] ] []
[ [ 'John', 'Anne' ], [ 'Mary', 'Ben' ], [ 'Zalgo', 'Kenny' ] ] []
[ [ 'John', 'Zalgo' ], [ 'Mary', 'Anne' ], [ 'Kenny', 'Ben' ] ] []
[ [ 'John', 'Zalgo' ], [ 'Mary', 'Kenny' ], [ 'Anne', 'Ben' ] ] []
[ [ 'John', 'Zalgo' ], [ 'Mary', 'Ben' ], [ 'Anne', 'Kenny' ] ] []
[ [ 'John', 'Kenny' ], [ 'Mary', 'Anne' ], [ 'Zalgo', 'Ben' ] ] []
[ [ 'John', 'Kenny' ], [ 'Mary', 'Zalgo' ], [ 'Anne', 'Ben' ] ] []
[ [ 'John', 'Kenny' ], [ 'Mary', 'Ben' ], [ 'Anne', 'Zalgo' ] ] []
[ [ 'John', 'Ben' ], [ 'Mary', 'Anne' ], [ 'Zalgo', 'Kenny' ] ] []
[ [ 'John', 'Ben' ], [ 'Mary', 'Zalgo' ], [ 'Anne', 'Kenny' ] ] []
[ [ 'John', 'Ben' ], [ 'Mary', 'Kenny' ], [ 'Anne', 'Zalgo' ] ] []

對於奇數(我們無法將每個人配對),未配對的將進入rest

# ["John", "Mary", "Anne", "Zalgo", "Kenny"]

[ [ 'John', 'Mary' ], [ 'Anne', 'Zalgo' ] ] [ 'Kenny' ]
[ [ 'John', 'Mary' ], [ 'Anne', 'Kenny' ] ] [ 'Zalgo' ]
[ [ 'John', 'Anne' ], [ 'Mary', 'Zalgo' ] ] [ 'Kenny' ]
[ [ 'John', 'Anne' ], [ 'Mary', 'Kenny' ] ] [ 'Zalgo' ]
[ [ 'John', 'Zalgo' ], [ 'Mary', 'Anne' ] ] [ 'Kenny' ]
[ [ 'John', 'Zalgo' ], [ 'Mary', 'Kenny' ] ] [ 'Anne' ]
[ [ 'John', 'Kenny' ], [ 'Mary', 'Anne' ] ] [ 'Zalgo' ]
[ [ 'John', 'Kenny' ], [ 'Mary', 'Zalgo' ] ] [ 'Anne' ]

取 1 個(所有對,可重復使用)

這樣的事情不行嗎? 需要額外注意確保輸入沒有重復項並對結果進行排序......

function generatePairs(ids) {
  const uniqueIds = Array.from(new Set(ids));
  const outSet = new Set();
  for (let i = 0; i < uniqueIds.length; i++) {
    for (let j = i + 1; j < uniqueIds.length; j++) {
      outSet.add(`${uniqueIds[i]}-${uniqueIds[j]}`);
    }
  }
  const out = Array.from(outSet);
  out.sort();
  return out;
}


console.log(generatePairs([1, 1, 2, 3, 4, 5, 5, 6]));

輸出是

[
  '1-2', '1-3', '1-4',
  '1-5', '1-6', '2-3',
  '2-4', '2-5', '2-6',
  '3-4', '3-5', '3-6',
  '4-5', '4-6', '5-6'
]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM