parwatcodes
parwatcodes

Reputation: 6796

Array Filter with custom requirement and data manipulation

const data = [{
    employee: 70,
    month: 0,
    year: 2017,
    id: 3,
    createdAt: '2017-09-15T09:42:37.000Z',
    updatedAt: '2017-09-15T09:42:37.000Z',
    organization: 41,
    version: 1
},
{
    employee: 70,
    month: 4,
    year: 2017,
    id: 4,
    createdAt: '2017-09-15T09:59:28.000Z',
    updatedAt: '2017-09-15T09:59:28.000Z',
    organization: 41,
    version: 2
},
{
    employee: 70,
    month: 4,
    year: 2017,
    id: 5,
    createdAt: '2017-09-15T10:00:35.000Z',
    updatedAt: '2017-09-15T10:00:35.000Z',
    organization: 41,
    version: 3
},
{
    employee: 70,
    month: 4,
    year: 2017,
    id: 6,
    createdAt: '2017-09-15T10:01:18.000Z',
    updatedAt: '2017-09-15T10:01:18.000Z',
    organization: 41,
    version: 4
},
{
    employee: 70,
    month: 4,
    year: 2017,
    id: 7,
    createdAt: '2017-09-15T10:07:11.000Z',
    updatedAt: '2017-09-15T10:07:11.000Z',
    organization: 41,
    version: 5
},
{
    employee: 70,
    month: 4,
    year: 2017,
    id: 8,
    createdAt: '2017-09-15T10:40:11.000Z',
    updatedAt: '2017-09-15T10:40:11.000Z',
    organization: 41,
    version: 6
},
{
    employee: 70,
    month: 4,
    year: 2017,
    id: 9,
    createdAt: '2017-09-15T10:40:58.000Z',
    updatedAt: '2017-09-15T10:40:58.000Z',
    organization: 41,
    version: 7
}, {
    employee: 70,
    month: 7,
    year: 2017,
    id: 10,
    createdAt: '2017-09-15T10:40:58.000Z',
    updatedAt: '2017-09-15T10:40:58.000Z',
    organization: 41,
    version: 6
}, {
    employee: 70,
    month: 7,
    year: 2017,
    id: 11,
    createdAt: '2017-09-15T10:40:58.000Z',
    updatedAt: '2017-09-15T10:40:58.000Z',
    organization: 41,
    version: 7
}];

const currentMonth = // 0, 11

Here i need to make an algorithm to get the details from the array,

I want to get the details from array as per the required month number.

  1. If the month number matches with the record present in Array, return it, and if there are multiple records of that month then it should return the month details by looking the highest value of version, suppose in the above array for the month 7 there are 2 records with version 6 and 7, so what i want is the object with highest version 7.

    There are 2 records for month 7, so i will get

    { employee: 70, month: 7, year: 2017, id: 11, createdAt: '2017-09-15T10:40:58.000Z', updatedAt: '2017-09-15T10:40:58.000Z', organization: 41, version: 7 // <<==== highest version }

  2. If the month number provided by user doesn't exists then it should look at the closet lowest month nearer to it, and provide the object with the highest version, But if there are more objects with lowest month number then it should take the data with highest version

    Suppose i want the record for month 5 or 6, but in the array there is no record for that month so i will look for the closet lowest month which is 4, there are muliple records for month 4 so, i will filter i will want to get the object with the highest version id

    which is

    { employee: 70, month: 4, year: 2017, id: 9, createdAt: '2017-09-15T10:40:58.000Z', updatedAt: '2017-09-15T10:40:58.000Z', organization: 41, version: 7 // <<======highest version }

  3. Based on rules here, if the month number provided doesn't exist and there are no records in earlier months, provide the object with the highest version from the month closest to the month number provided.

What i have tried so far is here.

This work looks pretty simple, but i think i am making it more complex.. Any Kind of help is much Appreciated.

const getLastEmployeeMonthVersion = data.filter(function (emp, index) {
    if (emp.month < currentMonth) {
        return _.inRange(currentMonth, data[index].month, data[data.length - 1].month) ? emp : emp
    }
});

employeeVersionForMonth = [...getLastEmployeeMonthVersion];
const getGroupByEmployee = employeeVersionForMonth.length && _.groupBy(employeeVersionForMonth, (v) => v.employee);
const employeeKeys = Object.keys(getGroupByEmployee);
let latestEmployeeVersion = [];

employeeKeys.forEach(emp => {
    const maxVersionId = _.maxBy(getGroupByEmployee[emp], (value) => value.version);
    latestEmployeeVersion.push(maxVersionId);
})

console.log(latestEmployeeVersion)

Upvotes: 1

Views: 81

Answers (4)

dork
dork

Reputation: 4578

Do you mean something like this?

const data = [{
  employee: 70,
  month: 0,
  year: 2017,
  id: 3,
  createdAt: '2017-09-15T09:42:37.000Z',
  updatedAt: '2017-09-15T09:42:37.000Z',
  organization: 41,
  version: 1
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 4,
  createdAt: '2017-09-15T09:59:28.000Z',
  updatedAt: '2017-09-15T09:59:28.000Z',
  organization: 41,
  version: 2
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 5,
  createdAt: '2017-09-15T10:00:35.000Z',
  updatedAt: '2017-09-15T10:00:35.000Z',
  organization: 41,
  version: 3
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 6,
  createdAt: '2017-09-15T10:01:18.000Z',
  updatedAt: '2017-09-15T10:01:18.000Z',
  organization: 41,
  version: 4
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 7,
  createdAt: '2017-09-15T10:07:11.000Z',
  updatedAt: '2017-09-15T10:07:11.000Z',
  organization: 41,
  version: 5
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 8,
  createdAt: '2017-09-15T10:40:11.000Z',
  updatedAt: '2017-09-15T10:40:11.000Z',
  organization: 41,
  version: 6
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 9,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 7
}, {
  employee: 70,
  month: 7,
  year: 2017,
  id: 10,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 6
}, {
  employee: 70,
  month: 7,
  year: 2017,
  id: 11,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 7
}];

const currentMonth = 7;
const monthLookup = data.reduce((prev, record) => {
  return record.month > prev && record.month <= currentMonth ? record.month : prev;
}, 0);
const record = data.filter((record) => record.month === monthLookup).reduce((prev, current) => {
	return prev.version > current.version ? prev : current;
});

console.log(record);

Update (adding the 3rd rule)

const data = [{
  employee: 70,
  month: 2,
  year: 2017,
  id: 3,
  createdAt: '2017-09-15T09:42:37.000Z',
  updatedAt: '2017-09-15T09:42:37.000Z',
  organization: 41,
  version: 1
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 4,
  createdAt: '2017-09-15T09:59:28.000Z',
  updatedAt: '2017-09-15T09:59:28.000Z',
  organization: 41,
  version: 2
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 5,
  createdAt: '2017-09-15T10:00:35.000Z',
  updatedAt: '2017-09-15T10:00:35.000Z',
  organization: 41,
  version: 3
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 6,
  createdAt: '2017-09-15T10:01:18.000Z',
  updatedAt: '2017-09-15T10:01:18.000Z',
  organization: 41,
  version: 4
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 7,
  createdAt: '2017-09-15T10:07:11.000Z',
  updatedAt: '2017-09-15T10:07:11.000Z',
  organization: 41,
  version: 5
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 8,
  createdAt: '2017-09-15T10:40:11.000Z',
  updatedAt: '2017-09-15T10:40:11.000Z',
  organization: 41,
  version: 6
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 9,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 7
}, {
  employee: 70,
  month: 7,
  year: 2017,
  id: 10,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 6
}, {
  employee: 70,
  month: 7,
  year: 2017,
  id: 11,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 7
}];

function getRecord(month) {
  // Check if a record exists in the current or earlier months.
  const existsInCurrentOrEarlierMonth = data.some((record) => record.month <= month);
  const monthLookup = existsInCurrentOrEarlierMonth
    // Get the max month number if a record exists in the current or earlier months.
    ? Math.max.apply(null, data.reduce((earlierMonths, record) => {
      if (record.month <= month) {
        earlierMonths.push(record.month);
      }

      return earlierMonths;
    }, []))
    // Get the min month number if no records exist in the current or earlier months.
    : Math.min.apply(null, data.reduce((laterMonths, record) => {
      if (record.month > month) {
        laterMonths.push(record.month);
      }

      return laterMonths;
    }, []));

  // Filter the data with the month lookup and return the record with the highest version.
  return data.filter((record) => record.month === monthLookup).reduce((prev, current) => {
    return current.version > prev.version ? current : prev;
  });
}

console.log('Month 1 (should get month 2\'s record):', getRecord(1));
console.log('Month 7 (should get month 7\'s record):', getRecord(7));
console.log('Month 6 (should get month 4\'s record):', getRecord(6));
console.log('Month 8 (should get month 7\'s record):', getRecord(8));

Upvotes: 0

Yogen Darji
Yogen Darji

Reputation: 3300

Here is another way to to implement that algorithm.

1. filter array with o.month <= currentMonth that will list all records having month is less than current month.

2. orderBy with month and then version.

3. head first record from ordered list that will be your record.

var result= _.head(
  _.orderBy(
    _.filter(data,
      function(o) {
        return o.month <= currentMonth;
      }), ['month', 'version'], ['desc', 'desc']));

const data = [{
  employee: 70,
  month: 0,
  year: 2017,
  id: 3,
  createdAt: '2017-09-15T09:42:37.000Z',
  updatedAt: '2017-09-15T09:42:37.000Z',
  organization: 41,
  version: 1
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 4,
  createdAt: '2017-09-15T09:59:28.000Z',
  updatedAt: '2017-09-15T09:59:28.000Z',
  organization: 41,
  version: 2
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 5,
  createdAt: '2017-09-15T10:00:35.000Z',
  updatedAt: '2017-09-15T10:00:35.000Z',
  organization: 41,
  version: 3
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 6,
  createdAt: '2017-09-15T10:01:18.000Z',
  updatedAt: '2017-09-15T10:01:18.000Z',
  organization: 41,
  version: 4
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 7,
  createdAt: '2017-09-15T10:07:11.000Z',
  updatedAt: '2017-09-15T10:07:11.000Z',
  organization: 41,
  version: 5
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 8,
  createdAt: '2017-09-15T10:40:11.000Z',
  updatedAt: '2017-09-15T10:40:11.000Z',
  organization: 41,
  version: 6
}, {
  employee: 70,
  month: 4,
  year: 2017,
  id: 9,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 7
}, {
  employee: 70,
  month: 7,
  year: 2017,
  id: 10,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 6
}, {
  employee: 70,
  month: 8,
  year: 2017,
  id: 11,
  createdAt: '2017-09-15T10:40:58.000Z',
  updatedAt: '2017-09-15T10:40:58.000Z',
  organization: 41,
  version: 7
}];

const currentMonth = 11;

var employeeVersionForMonth = _.head(
  _.orderBy(
    _.filter(data,
      function(o) {
        return o.month <= currentMonth;
      }), ['month', 'version'], ['desc', 'desc']));


console.log(employeeVersionForMonth);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Upvotes: 1

Hardeep Singh
Hardeep Singh

Reputation: 780

just Call following function get result as per your requirement

function findMonthRecords(month, recur)
{
    var ret_records = [];

    for (i in data)
    {
        var record = data[i];

        if (record["month"] == month)
        {
            ret_records.push(record)
        }
    }   

    if (ret_records.length == 0 && recur)
    {
        for (var a = month - 1; a >= 0; a--) 
        {
            ret_records = findMonthRecords(a, false)

            if (ret_records.length > 0)
            {
                return ret_records;
            }   
        }

        for (var a = month + 1; a < 12; a++) 
        {
            ret_records = findMonthRecords(a, false)
            console.log(a);
            console.log(ret_records);
            if (ret_records.length > 0)
            {
                return ret_records;
            }   
        }   
    }   

    return ret_records;
}


console.log(findMonthRecords(2, true));

Upvotes: 1

stdob--
stdob--

Reputation: 29157

One walk:

const currentMonth = 5 // 0, 5, 10

let fMonth = -Infinity
let fVersion = -Infinity
let fIndex

for (let i = 0; i < data.length; i++) {
  let item = data[i]
  if ( (item.month > fMonth && item.month <= currentMonth) ||
       (item.month === fMonth && item.version > fVersion)
     ) {
    fMonth = item.month
    fVersion = item.version
    fIndex = i
  }
}

Upvotes: 0

Related Questions