具有自定义要求和数据操作的数组过滤器

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

这里我需要做一个算法来从数组中获取细节,

我想根据所需的月份数从数组中获取详细信息。

  1. 如果月份编号与数组中存在的记录相匹配,return 它,如果该月份有多个记录,那么它应该 return 月份详细信息寻找版本的最高值,假设在上面的第 7 个月的数组中有 2 条版本为 6 和 7 的记录,所以我想要的是版本最高的对象 7.

    第 7 个月有 2 条记录,所以我会得到

    { 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. 如果用户提供的月数不存在则查看离它最近的最低月,并提供版本最高的对象,但如果有更多的对象最低月份数,那么它应该采用最高版本的数据

    假设我想要第 5 个月或第 6 个月的记录,但在数组中没有那个月的记录,所以我将寻找壁橱最低的月份,即 4,第 4 个月有多个记录,所以,我将过滤我将要获得具有最高版本 ID

    的对象

    { 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,如果提供的月份编号不存在且之前月份没有记录,则提供从最接近提供的月份编号的月份开始的最高版本的对象.

到目前为止我尝试过的是这里。

这项工作看起来很简单,但我想我把它变得更复杂了.. 任何类型的帮助都非常 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)

一次步行:

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
  }
}

你的意思是这样的吗?

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);

更新 (添加 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));

只需调用以下函数即可根据您的要求获得结果

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));

这是实现该算法的另一种方法。

1。 filter 数组 o.month <= currentMonth 将列出所有月份小于当前月份的记录。

2。 orderBymonth 然后 version.

3。 head ordered 列表中的第一条记录将成为您的记录。

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/lodash@4.17.4/lodash.min.js"></script>