在对象嵌套数组中查找对象的路径

人气:562 发布:2022-10-16 标签: functional-programming ramda.js

问题描述

我有一个对象,其参数包含对象的和数组。我收到1个对象ID,我需要在整个混乱中找到它的位置。通过过程性编程,我使其能够正常工作:

const opportunitiesById =  {
  1: [
    { id: 1, name: 'offer 1' },
    { id: 2, name: 'offer 1' }
  ],
  2: [
    { id: 3, name: 'offer 1' },
    { id: 4, name: 'offer 1' }
  ],
  3: [
    { id: 5, name: 'offer 1' },
    { id: 6, name: 'offer 1' }
  ]
};

const findObjectIdByOfferId = (offerId) => {
  let opportunityId;
  let offerPosition;
  const opportunities = Object.keys(opportunitiesById);

  opportunities.forEach(opportunity => {
    const offers = opportunitiesById[opportunity];

    offers.forEach((offer, index) => {
      if (offer.id === offerId) {
        opportunityId = Number(opportunity);
        offerPosition = index;
      }
    })
  });

return { offerPosition, opportunityId };
}

console.log(findObjectIdByOfferId(6)); // returns { offerPosition: 1, opportunityId: 3 }

然而,这并不美观,我想以一种函数的方式来实现。 我已经查看了Ramda,当我查看单个优惠数组时,我可以找到优惠,但我找不到一种方法来查看整个对象=>每个数组,以找到我的优惠的路径。

R.findIndex(R.propEq('id', offerId))(opportunitiesById[1]);

我需要知道路径的原因是,我随后需要使用新数据修改该报价,并将其更新回原来的位置。

感谢您的帮助

推荐答案

我会将您的对象转换成对。

举个例子,转换一下:

{ 1: [{id:10}, {id:20}],
  2: [{id:11}, {id:21}] }

进入:

[ [1, [{id:10}, {id:20}]],
  [2, [{id:11}, {id:21}]] ]
然后,您可以迭代该数组,并将每个报价数组缩减为您要查找的报价的索引。假设您正在寻找优惠#21,则上面的数组将变为:

[ [1, -1],
  [2,  1] ]

然后返回第二个元素不等于-1的第一个元组:

[2, 1]

我建议这样做:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const opportunitiesById =  {
  1: [ { id: 10, name: 'offer 1' },
       { id: 20, name: 'offer 2' } ],
  2: [ { id: 11, name: 'offer 3' },
       { id: 21, name: 'offer 4' } ],
  3: [ { id: 12, name: 'offer 5' },
       { id: 22, name: 'offer 6' } ]
};

const findOfferPath = (id, offers) =>
  pipe(
    toPairs,
    transduce(
      compose(
        map(over(lensIndex(1), findIndex(propEq('id', id)))),
        reject(pathEq([1], -1)),
        take(1)),
      concat,
      []))
    (offers);


console.log(findOfferPath(21, opportunitiesById));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {pipe, transduce, compose, map, over, lensIndex, findIndex, propEq, reject, pathEq, take, concat, toPairs} = R;</script>

然后您可以按照您认为合适的方式修改您的报价:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const opportunitiesById =  {
  1: [ { id: 10, name: 'offer 1' },
       { id: 20, name: 'offer 2' } ],
  2: [ { id: 11, name: 'offer 3' },
       { id: 21, name: 'offer 4' } ],
  3: [ { id: 12, name: 'offer 5' },
       { id: 22, name: 'offer 6' } ]
};

const updateOffer = (path, update, offers) =>
  over(lensPath(path), assoc('name', update), offers);

console.log(updateOffer(["2", 1], '', opportunitiesById));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {over, lensPath, assoc} = R;</script>

732