将具有相似键的对象插入到数组中,键是否存在

Insert Objects with similar keys into an array, is the key exists

这可能是我无法解决的基本问题。我有一个从 API 接收到的初始数组值,如下所示:

const primaryArray = [
    {
    startDate: '01-01-2021',
    endDate: '11-01-2021',
    refs: [
        {
        refId: "FL013",
                year: "2021"
      }
    ]
  },
  {
    startDate: '01-02-2021',
    endDate: '28-02-2021',
    refs: [
        {
        refId: "FL013",
                year: "2021"
      }
    ]
  },
  {
    startDate: '03-05-2020',
    endDate: '10-06-2020',
    refs: [
        {
        refId: "FL013",
                year: "2020"
      }
    ]
  },
  {
    startDate: '25-03-2019',
    endDate: '25-04-2019',
    refs: [
        {
        refId: "FL013",
                year: "2019"
      }
    ]
  }
];

由于 2021 年的两个对象与 'FL013' 共享相同的引用键,我想将它们转换为这样的形式,所有对象都从数组中分离出来:

{
    2021: { 
    'year': 2021, 
    'refIds': ['FL013', 'FL013'], 
    'duration': { 
      'FL013': [
        {
          startDate: '01-01-2021',
          endDate: '11-01-2021'
        }, 
        {
          startDate: '01-02-2021',
          endDate: '28-02-2021',
        }
       ]
     }
    }
},
{
    2020: { year: 2020, 'refIds': ['FL013'], 'duration': { 'FL013': {
                                               startDate: '03-05-2020',
                                               endDate: '10-06-2020',
                                             }
          }
},
{
    2019: { year: 2019, 'refIds': ['FL013'], 'duration': { 'FL013': {
                                               startDate: '25-03-2019',
                                               endDate: '25-04-2019',
                                             }
          }
}

我尝试使用 JS reduce 来做同样的事情,但是用两个日期对象创建年份数组总是给我一个错误。

这是我到目前为止试图实现的目标:

const flatArray = primaryArray && primaryArray.reduce(
(acc, {startDate, endDate, refs}, currentIndex) => {

  const year = refs && refs[0] && refs[0].year;
  const refId = refs && refs[0] && refs[0].refId;
            
   if (
        year &&
        refId &&
        startDate &&
        endDate &&
        !Object.prototype.hasOwnProperty.call(acc, year)
      ) {
           acc[year] = {
               year,
               refIds: [refId],
               duration: {
                           [refId]: {
                             startDate,
                             endDate,
                         },
               },
           };
        } else {
            if (year) {
                acc[year].refIds.push(refId);
                acc[year]['duration'][refId] = {
                  startDate,
                  endDate,
                };
              }
            }
   return acc;
},{});

我使用两种方法修改了上面的代码以获得准确的结果:首先,推送累加器中收到的日期对象

acc[year]['duration'][refId].push({ startDate, endDate }). 

这会引发错误:

Uncaught TypeError: acc[year].duration[refId].push is not a function

或者其次,直接应用[]表示法(据我所知不适用)。

这是相同的工作 link: https://onecompiler.com/javascript/3wwzz3f4s

任何解决相同问题的帮助,非常感谢。

你可以用 Array.prototype.reduce() 做这样的事情:

const primaryArray = [
    {
    startDate: '01-01-2021',
    endDate: '11-01-2021',
    refs: [
        {
        refId: "FL013",
                year: "2021"
      }
    ]
  },
  {
    startDate: '01-02-2021',
    endDate: '28-02-2021',
    refs: [
        {
        refId: "FL013",
                year: "2021"
      }
    ]
  },
  {
    startDate: '03-05-2020',
    endDate: '10-06-2020',
    refs: [
        {
        refId: "FL013",
                year: "2020"
      }
    ]
  },
  {
    startDate: '25-03-2019',
    endDate: '25-04-2019',
    refs: [
        {
        refId: "FL013",
                year: "2019"
      }
    ]
  }
];

const res = primaryArray.reduce((acc, {refs, startDate, endDate}) => {
  if(!acc[refs[0].year]) {   
    acc[refs[0].year] = {
      year: refs[0].year,
      refIds: [refs[0].refId],
      duration: {
        [refs[0].refId]: {
          startDate: startDate,
          endDate: endDate
        }
      }
    }
  } else {
    acc[refs[0].year].refIds.push(refs[0].refId);
    acc[refs[0].year].duration = {
      [refs[0].refId]: [
        {...acc[refs[0].year].duration[refs[0].refId]},
        {
          startDate: startDate,
          endDate: endDate
        }
      ]

    }
  }

  return acc;
}, {})

console.log(res);

另一种选择是测试它是否已经是一个数组,如果不是则创建它。 typeof acc[year]['duration'][refId] !== '[object Array]'

const flatArray = primaryArray && primaryArray.reduce(
(acc, {startDate, endDate, refs}, currentIndex) => {

  const year = refs && refs[0] && refs[0].year;
  const refId = refs && refs[0] && refs[0].refId;


            
   if (
        year &&
        refId &&
        startDate &&
        endDate &&
        !Object.prototype.hasOwnProperty.call(acc, year)
      ) {
           acc[year] = {
               year,
               refIds: [refId],
               duration: {
                           [refId]: {
                             startDate,
                             endDate,
                         },
               },
           };
        } else {
            if (year) {
                acc[year].refIds.push(refId);
                if (acc[year]['duration'][refId] && typeof acc[year]['duration'][refId] !== '[object Array]') {
                    acc[year]['duration'][refId] = [acc[year]['duration'][refId]]
                }

                acc[year]['duration'][refId].push({
                  startDate,
                  endDate,
                })
              }
            }
   return acc;
},{});

const primaryArray = [{
    startDate: '01-01-2021',
    endDate: '11-01-2021',
    refs: [{
      refId: 'FL013',
      year: '2021',
    }, ],
  },
  {
    startDate: '01-02-2021',
    endDate: '28-02-2021',
    refs: [{
      refId: 'FL013',
      year: '2021',
    }, ],
  },
  {
    startDate: '03-05-2020',
    endDate: '10-06-2020',
    refs: [{
      refId: 'FL013',
      year: '2020',
    }, ],
  },
  {
    startDate: '25-03-2019',
    endDate: '25-04-2019',
    refs: [{
      refId: 'FL013',
      year: '2019',
    }, ],
  },
];

const result = primaryArray.reduce((acc, cur) => {
  const {
    startDate,
    endDate,
    refs: [{
      refId,
      year
    }],
  } = cur;
  const entry = acc[year];
  const yearExistsAlready = entry !== undefined;
  if (yearExistsAlready) {
    entry.refIds.push(refId);
    const duration = entry.duration[refId];
    const durationExistsAlready = duration !== undefined;
    if (durationExistsAlready) entry.duration[refId].push({
      startDate,
      endDate
    });
    else entry.duration = {
      refId: {
        startDate,
        endDate
      }
    };
  } else {
    acc[year] = {
      year,
      refIds: [refId],
      duration: {
        [refId]: [{
          startDate,
          endDate
        }],
      },
    };
  }
  return acc;
}, {});
console.log(result)