Нахождение ближайшей даты в массиве - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь найти самую высокую дату среди массива объектов с разными датами, которые будут приписываться каждому объекту.Код прекрасно работает до тех пор, пока даты превышают 1 января 1970 года, но любая другая дата до этого вызывает ошибку.Как я могу это исправить, сохранив те же даты?Я знаю, что могу использовать get (Time) для всех дат, но есть ли способ обойти это?Спасибо.

var playerData = [
    {name: "John"},
    {name: "Bill"},
    {name: "Bob"},
    {name: "Jim"},
    
];
    
var dateOne = new Date(1940,02,05);
var dateTwo = new Date(1950, 06,18);
var dateThree = new Date(1650,07,12);
var dateFour = new Date(1300, 03,25);
    
playerData[0].date = dateOne;
playerData[1].date = dateTwo;
playerData[2].date = dateThree;
playerData[3].date = dateFour;

function findHighDate() {
    var highDateSoFar = null;
    var result;
    for (var i = 0; i < playerData.length; i++) {
        if (playerData[i].date > highDateSoFar) {
            result = playerData[i];
            highDateSoFar = playerData[i].date;
        }
        else if (playerData[i].date === highDateSoFar) {	
            result = 'equal';
        
    }
    }
    return result;
}
    
var highPlayer = findHighDate();
var highPlayerName = highPlayer.name;
var highPlayerIndex = playerData.indexOf(highPlayer);
var highPlayerDate = highPlayer.date;
console.log({highPlayer},{highPlayerIndex},{highPlayerName},{highPlayerDate});

Ответы [ 6 ]

0 голосов
/ 15 февраля 2019

Я часто нахожу, что легче решить проблему, поднявшись на один или два уровня абстракции.Если мы хотим найти объект, который имеет свойство с самой высокой датой, я мог бы начать с написания чего-то, что находит максимум по любому данному свойству.Но даже лучше, я мог бы снабдить его функцией и найти значение, которое максимизирует эту функцию.Оказывается, что это так же легко написать, как дату, и это отделяет логику нахождения максимума от обыденного бита выбора свойства даты.

Так что здесь мы могли бы написать

const maximumBy = (fn) => (data) => 
  data.reduce((m, x) => fn(x) > fn(m) ? x : m, data[0])

const findHighestPlayer = maximumBy(player => player.date)

var playerData = [
    {name: "John", date: new Date(1940, 2,  5)},
    {name: "Bill", date: new Date(1950, 6, 18)},
    {name: "Bob",  date: new Date(1650, 7, 12)},
    {name: "Jim",  date: new Date(1300, 3, 25)},
];


console.log(findHighestPlayer(playerData))

Обратите внимание, что если ваш массив пуст, он вернет undefined, но трудно знать, что еще делать.Вы всегда можете добавить параметр значения по умолчанию, если это важно исправить.

0 голосов
/ 15 февраля 2019

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

Так что просто избегайте этого сравнения, инициализируя highDateSoFar каким-либо другим значением (например, -Infinity или первой датой в массиве), или проверяйте, чтобы оно было null , например

var playerData = [
    {name: "John", date: new Date(1940, 2,  5)},
    {name: "Bill", date: new Date(1950, 6, 18)},
    {name: "Bob",  date: new Date(1650, 7, 12)},
    {name: "Jim",  date: new Date(1300, 3, 25)},
];

function findHighDate(data) {
  var highDateSoFar = null; 
  var result;
  
  for (var i=0; i < data.length; i++) {

    if (highDateSoFar === null || data[i].date > highDateSoFar) {
      result = data[i];
      highDateSoFar = data[i].date;
    }
  }
  return result ;
}

console.log( findHighDate(playerData) );

Также выражение playerData[i].date === highDateSoFar будет истинным, только если playerData [i] .date и highDateSoFar ссылаются на одну и ту же датуобъект, который не может быть истинным в логике функции.

Вы также можете использовать уменьшить для этого:

var playerData = [
  {name: "John", date: new Date(1940, 2,  5)},
  {name: "Bill", date: new Date(1950, 6, 18)},
  {name: "Bob",  date: new Date(1650, 7, 12)},
  {name: "Jim",  date: new Date(1300, 3, 25)},
];

function getHighest(data) {
  return data.reduce((acc, high) => {
     acc = high.date > acc.date? high : acc;
     return acc;
  }, {date:-Infinity});
}

console.log(getHighest(playerData));
0 голосов
/ 15 февраля 2019

Вы можете сделать это.Я упростил логику.Вы также можете использовать sort (), как предлагали другие.

var playerData = [
    {name: "John"},
    {name: "Bill"},
    {name: "Bob"},
    {name: "Jim"},
    
];
    
var dateOne = new Date(1940,02,05);
var dateTwo = new Date(1950, 06,18);
var dateThree = new Date(1650,07,12);
var dateFour = new Date(1300, 03,25);
    
playerData[0].date = dateOne;
playerData[1].date = dateTwo;
playerData[2].date = dateThree;
playerData[3].date = dateFour;

function playerWithHighestDate() {
	// start by assuming player 0 is highest
    var winner = 0;
    
    // start at one as we dont need to compare with player 0
    for (var i = 1; i < playerData.length; i++) {
    		// compares players date
        if (playerData[i].date >= playerData[winner].date) {
            winner = i;
        }
    }
    
    // returns the winner index
    return winner;
}

// get index with highest date
var highPlayerIndex = playerWithHighestDate();
var highPlayer = playerData[highPlayerIndex];
var highPlayerName = highPlayer.name;
var highPlayerDate = highPlayer.date;
console.log({highPlayer},{highPlayerIndex},{highPlayerName},{highPlayerDate});
0 голосов
/ 15 февраля 2019

Вместо сравнения дат вы можете сравнить строки и использовать Array.sort, чтобы упорядочить их в порядке убывания, а затем получить первый элемент:

const playerData = [
  {name: "John", date: '1940-02-05' },
  {name: "Bill", date: '1950-06-18' },
  {name: "Bob", date: '1650-07-12' },
  {name: "Jim", date: '1300-03-25' },
];

function findHighDate() {
  return playerData.sort((a, b) => b.date.localeCompare(a.date))[0];
}
    
const highPlayer = findHighDate();
const highPlayerName = highPlayer.name;
const highPlayerIndex = playerData.indexOf(highPlayer);
const highPlayerDate = new Date(highPlayer.date);
console.log({ highPlayer, highPlayerIndex, highPlayerName, highPlayerDate });

Или вы также можете придерживаться дат и сравнивать их, используя Date.getTime() для сортировки массива:

const playerData = [
  {name: "John", date: new Date('1940-02-05') },
  {name: "Bill", date: new Date('1950-06-18') },
  {name: "Bob", date: new Date('1650-07-12') },
  {name: "Jim", date: new Date('1300-03-25') },
];

function findHighDate() {
  return playerData.sort((a, b) => b.date.getTime() - a.date.getTime())[0];
}
    
const highPlayer = findHighDate();
const highPlayerName = highPlayer.name;
const highPlayerIndex = playerData.indexOf(highPlayer);
const highPlayerDate = highPlayer.date;
console.log({ highPlayer, highPlayerIndex, highPlayerName, highPlayerDate });

Как отметил @Scott Sauyet в комментариях ниже, использование Array.sort может быть излишним для вашего сценария.

Вы можете найти свою самую высокую дату снемного больше кода и помощь reduce:

const playerData = [
  {name: "John", date: new Date('1940-02-05') },
  {name: "Bill", date: new Date('1950-06-18') },
  {name: "Bob", date: new Date('1650-07-12') },
  {name: "Jim", date: new Date('1300-03-25') },
];

function findHighDate() {
  return playerData.reduce((highest, player) => {
    return highest.date.getTime() > player.date.getTime() ? highest : player;
  }, playerData[0]);
}
    
const highPlayer = findHighDate();
const highPlayerName = highPlayer.name;
const highPlayerIndex = playerData.indexOf(highPlayer);
const highPlayerDate = highPlayer.date;
console.log({ highPlayer, highPlayerIndex, highPlayerName, highPlayerDate });
0 голосов
/ 15 февраля 2019

Можно предварительно назначить дату первого человека, чтобы сделать сравнение следующим образом.

var playerData = [
    {name: "John"},
    {name: "Bill"},
    {name: "Bob"},
    {name: "Jim"},

];

var dateOne = new Date(1940,02,05);
var dateTwo = new Date(1950, 06,18);
var dateThree = new Date(1650,07,12);
var dateFour = new Date(1300, 03,25);

playerData[0].date = dateOne;
playerData[1].date = dateTwo;
playerData[2].date = dateThree;
playerData[3].date = dateFour;

function findHighDate() {
    console.log(playerData);
    var highDateSoFar = playerData[0].date;
    var result = playerData[0];
    for (var i = 0; i < playerData.length; i++) {
        if (playerData[i].date > highDateSoFar) {
            result = playerData[i];
            highDateSoFar = playerData[i].date;
        }
        else if (playerData[i].date === highDateSoFar) {    

    }
    }
    return result;
}

var highPlayer = findHighDate();
var highPlayerName = highPlayer.name;
var highPlayerIndex = playerData.indexOf(highPlayer);
var highPlayerDate = highPlayer.date;
console.log({highPlayer},{highPlayerIndex},{highPlayerName},{highPlayerDate});
0 голосов
/ 15 февраля 2019

Если вы используете getTime() в датах, то до 1970 года просто будут отрицательными, поэтому обычные математические сравнения работают нормально.Ниже я просто сортирую данные вашего игрока по дате (максимум сначала).Если вы хотите самый высокий, просто возьмите первый элемент в массиве:

var playerData = [
  {name: "John"},
  {name: "Bill"},
  {name: "Bob"},
  {name: "Jim"},   
]
    
playerData[0].date = new Date(1940, 02, 05)
playerData[1].date = new Date(1950, 06, 18)
playerData[2].date = new Date(1650, 07, 12)
playerData[3].date = new Date(1300, 03, 25)

playerData.sort((a, b) => b.date.getTime() - a.date.getTime())

console.log(playerData)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...