查找独特的物品收藏

时间:2019-04-06 19:26:42

标签: javascript arrays dictionary search

我有一张卡片列表,其中包含“组”中的神奇宝贝卡片。数据以JSON格式检索(格式化/查询不在我的控制范围内)。

let myList = `
  [{'hand': '1', 'cards': {'charmander','pikachu','squirtle'}},
   {'hand': '2', 'cards': {'charmander','gyarados','jigglypuff'}},
   {'hand': '3', 'cards': {'balbasaur','blastoise','mankey'}}]
  `;

我不确定我可以用来在该列表中找到唯一手牌的原因,即第三手牌将是唯一的,因为它不包含其他手牌中的任何其他牌。 / p>

我创建了一个地图,并使用将每只 hand 变成一个字符串用作键,然后检查该键是否已经存在。但是根据以上数据,我不确定如何确保手牌3 是真正独特的手牌,因为其他手牌中没有其他手牌。

cards = JSON.parse(myList);
let cardMap = new Map();
cards.map((hands) => {
   let handAsStr = hands.cards.toString();
   let matchingValue = cardMap.has(handAsStr);
   if (matchingValue) {
      console.log("Entry exists - Not adding " + handAsStr );
   } 
   else {
      console.log("Adding: " + handAsStr )
      cardMap.set(handAsStr , {hand: hands.hand});
   }
});

我考虑过将名称转换为十六进制值,然后搜索该十六进制值是否存在于其他位置,但这似乎令人生畏且效率低下。

有指针吗?

3 个答案:

答案 0 :(得分:2)

假设一个cards的数组,您可以对所有集合的所有纸牌进行计数,如果所有纸牌的计数都为1,则可以通过检查纸牌来过滤该数组。

function findUnique(array) {
    var count = new Map;
    array.forEach(({ cards }) => cards.forEach(c => count.set(c, (count.get(c) || 0) + 1)));
    return array.filter(({ cards }) => cards.every(c => count.get(c) === 1));
}

var array = [{ hand: '1', cards: ['charmander', 'pikachu', 'squirtle'] }, { hand: '2', cards: ['charmander', 'gyarados', 'jigglypuff'] }, { hand: '3', cards: ['balbasaur', 'blastoise', 'mankey'] }];

console.log(findUnique(array));

答案 1 :(得分:1)

您的字符串不是有效的JSON,我建议将cards更改为数组,并将'替换为"

使用JSON.parse()进行解析后,您可以使用reduce()来构建地图,以获取每张卡的出现次数。然后,您可以使用该地图过滤列表并仅保留卡片仅出现一次的项目。

const myList = `[
 {'hand': '1', 'cards': ['charmander','pikachu','squirtle']},
 {'hand': '2', 'cards': ['charmander','gyarados','jigglypuff']},
 {'hand': '3', 'cards': ['balbasaur','blastoise','mankey']}
]`;

const list = JSON.parse(myList.replace(/'/g, '"'));

const allCards = list.reduce((acc, { cards }) => {
  cards.forEach(x => acc[x] = acc[x] ? acc[x] + 1 : 1);
  return acc;
}, {});

const uniqueItems = list.filter(({ cards }) => cards.every(x => allCards[x] === 1));

console.log(uniqueItems)

答案 2 :(得分:1)

将数组中的所有项目添加到SetuniqueSet)中。用嵌套的Array.forEach()迭代卡片。如果在cardMap)中找到objByCardMap,则从Set中删除当前对象,并将与卡片一起存储在地图中的对象删除。传播Set并返回唯一项数组:

const findUniqueHand = array => {
  const uniqueSet = new Set(array);
  const objByCardMap = new Map();
  
  // iterate the array and then the cards
  array.forEach(o => o.cards.forEach(c => {
    if(objByCardMap.has(c)) { // if a card is found in the Map
      uniqueSet.delete(objByCardMap.get(c)); // remove the object in the map
      uniqueSet.delete(o); // remove the current object
    }
    else objByCardMap.set(c, o); // add the card and it's object ot the map
  }));

  return [...uniqueSet];
}

const array = [{ hand: '1', cards: ['charmander', 'pikachu', 'squirtle'] }, { hand: '2', cards: ['charmander', 'gyarados', 'jigglypuff'] }, { hand: '3', cards: ['balbasaur', 'blastoise', 'mankey'] }];

const result = findUniqueHand(array);

console.log(result);