Я пытаюсь создать колоду из 52 карт. Я могу легко создать его с помощью двойного цикла for, но он имеет сложность O (n2). Итак, я пытался поиграть с методами массива map () и forEach (), но все сложно, чтобы они возвращали вещи. Вот мой код ниже.

(function deckCreate() {
  var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
  var suits = ["clubs", "diamonds", "hearts", "spades"];
  var newDeck = values.map(function(xValue) {
    suits.forEach(function(xSuit) {
      return [xSuit,xValue];
    });
  });
  return newDeck;
}());

Это дает массив длиной 13 все неопределенное внутри. Я пытался поменять местами forEach () перед map (), но результат был тот же.

Проблема, которую я обнаружил в то время, когда console.log () внутри этих функций заключалась в том, что элементы не отображались друг на друга, а печатались по отдельности. В чем может быть проблема?

1
Jamie 7 Янв 2017 в 23:47

4 ответа

Лучший ответ

Вы ничего не возвращаете из своей функции map, поэтому неявное возвращаемое значение равно undefined, следовательно, ваш массив из 13 undefined значений.

suits.forEach должен быть return suits.map. Это даст вам массив из 13 элементов, где каждый элемент представляет собой массив из четырех элементов, где каждый элемент массива inner представляет собой массив из двух элементов [suit, value]. Затем вы можете reduce массив верхнего уровня в массив из 52 элементов, который вы ищете:

var newDeck = values.map(function(xValue) {
  return suits.map(function(xSuit) {
    return [xSuit,xValue];
  });
}).reduce(function (a, b) { return a.concat(b) });
0
meagar 7 Янв 2017 в 20:56

Причина, по которой у вас возникают проблемы, заключается в том, что вы не возвращаетесь из своего внешнего .map() обратного вызова. Даже если вы это сделали, [].forEach всегда возвращает undefined, независимо от того, что происходит внутри его обратного вызова.

Итак, поскольку вы используете forEach для итерации внутреннего массива, вы получаете массив из 13 неопределенных из map.

То, что вы должны использовать, это .map() до конца и возвращаться на каждом этапе пути:

const first = [1, 2, 3];
const second = ['a', 'b', 'c'];

const mapped = first.map(function(digit) {
  return second.map(function(letter) {
    return [digit, letter];
    });
  });

console.log(mapped);

Видя, как вы явно пытаетесь учиться и улучшать себя, я оставлю вас, чтобы приспособить этот пример к вашему конкретному случаю.

Постскриптум Если вам нужен плоский массив, посмотрите на [].reduce() и [].concat().

0
Madara's Ghost 7 Янв 2017 в 20:52

Я думаю, что лучше это упростить.

Мы знаем, что всего 4 костюма, поэтому достаточно получить список по названию костюма:

function createDeck() {
  var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
  var deck = {"clubs": values.slice(), "diamonds": values.slice(), "hearts": values.slice(), "spades": values.slice()};
  return deck;
}

var deck = createDeck();

console.log('CLUBS:', deck.clubs);
console.log('DIAMONDS:', deck.diamonds);
console.log('HEARTS:', deck.hearts);
console.log('SPADES:', deck.spades);

Постскриптум в моем случае я создам класс, который делает генерацию, итерацию и т. д., чтобы легко его использовать.

function Deck() {
  var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
  var suits = ['clubs', 'diamonds', 'spades', 'hearts'];
  
  this.getSuits = function() {return suits.splice();}
  this.getValues = function() {return values.splice();}
  
  var asObject;
  this.asObject = function() {
    if(asObject) return asObject;
    
    asObject = {};
    suits.map(function(suit) {
      asObject[suit] = values.slice();
    });
    return asObject;
  };
  
  var asArray;
  this.asArray = function() {
    if(asArray) return asArray;
    asArray = [];
    
    suits.map(function(suit) {
      values.map(function(value) {
        asArray.push([suit, value]);
      });
    });
    return asArray;
  }
  
  this.iterate = function(fn) {
    this.asArray().map(fn);  
  }
}

var deck = new Deck();

deck.iterate(function(card) {
  console.log('CARD: ', card[0], card[1]);             
});

console.log(deck.asObject());
console.log(deck.asArray());
1
num8er 7 Янв 2017 в 21:41

Используйте простой цикл for. Используйте suits[Math.floor(i / 13)], чтобы получить правильный костюм, и используйте оператор остатка %, чтобы получить номер карты для каждой масти:

function deckCreate() {
  var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
  var suits = ["clubs", "diamonds", "hearts", "spades"];
  var newDeck = [];

  for (var i = 0; i < 52; i++) {
    newDeck.push([suits[Math.floor(i / 13)], values[i % 13]]);
  }

  return newDeck;
}

var result = deckCreate();

console.log(result);
1
Ori Drori 7 Янв 2017 в 21:10