Ramda to loop over array

人盡茶涼 提交于 2020-01-11 13:10:51

问题


Loop may be the wrong term, but it kind of describes what I am attempting. I want to give structure to flat data, but I also need to keep track of the array it came from.

Basically my rules are (per array):

  1. If level 1 exists- give it the name of the item, and a typechild array. EACH time a level 1 appears (even in the same array) it should create a new entry.

  2. Inside typechild, put the any items with level >1

  3. If NO level 1 exists- give it the name of the item, and a typechild array.

My code below is almost there, with the exception that it should create an array EVERYTIME it sees a level 1. My example will make sense:

Input data

 [
  {
    "title": "Test 1",
    "type": [{
        "name": "Animal",
        "level": 1
      },
      {
        "name": "Food",
        "level": 1
      },
      {
        "name": "Chicken",
        "level": 3
      }
    ]
  },
  {
    "title": "Test 2",
    "type": [{
      "name": "Foo",
      "level": 2
    }]
  }
]

Note: Animal and Food are both LEVEL 1 items. So it should create two ARRAYS like so...

Desired output

[
    {
        name: "Animal",
        typechild: [
            {
                level: 2,
                name: "Chicken"
            }
        ]
    },
    {
        name: "Food",
        typechild: [
            {
                level: 2,
                name: "Chicken"
            }
        ]
    },
    {
        name: "NoName",
        typechild: [
            {
                level: 2,
                name: "Foo"
            }
        ]
    }
]

Ramda attempt (try here: https://dpaste.de/JQHw):

const levelEq = (n) => pipe(prop('level'), equals(n));
const topLevel = pipe(prop('type'), find(levelEq(1)));
const topLevelName = pipe(topLevel, propOr('NoName', 'name'));
const extract2ndLevel = pipe(pluck('type'), flatten, filter(levelEq(2)));

const convert = pipe(
  groupBy(topLevelName),
  map(extract2ndLevel),
  map(uniq),
  toPairs,
  map(zipObj(['name', 'typechild']))
);

回答1:


Something like this?

var output = [{
  "name": "Animal",
  "typechild": [{
    "name": "Chicken",
    "level": 3
  }, {
    "name": "Dog",
    "level": 2
  }]
}, {
  "name": "Food",
  "typechild": [{
    "name": "Chicken",
    "level": 3
  }]
}, {
  "name": "No name",
  "typechild": [{
    "name": "Foo",
    "level": 2
  }, {
    "name": "Baz",
    "level": 2
  }]
}]


let out = {},
  typechild = {},
  k;

const data = [{
  "title": "Test 1",
  "type": [{
    "name": "Animal",
    "level": 1
  }, {
    "name": "Food",
    "level": 1
  }, {
    "name": "Chicken",
    "level": 3
  }]
}, {
  "title": "Test 2",
  "type": [{
    "name": "Foo",
    "level": 2
  }]
}, {
  "title": "Test 3",
  "type": [{
    "name": "Baz",
    "level": 2
  }]
}, {
  "title": "Test 4",
  "type": [{
    "name": "Animal",
    "level": 1
  }, {
    "name": "Dog",
    "level": 2
  }]
}]


data.forEach((node) => {
  k = false;
  typechild[node.title] = [];
  node.type && node.type.forEach((t, i) => {
    if (t.level == 1) {
      k = true;

      !out[t.name] ? out[t.name] = {
        name: t.name,
        typechild: typechild[node.title]
      } : out[t.name].typechild = out[t.name].typechild.concat(typechild[node.title]);
    } else {
      typechild[node.title].push(t);
    }
    if (i == node.type.length - 1 && !k && typechild[node.title].length) {
      out['No name'] = out['No name'] || {
        name: 'No name',
        typechild: []
      };

      out['No name'].typechild = out['No name'].typechild.concat(typechild[node.title]);
    }
  });
});

console.log(JSON.stringify(Object.values(out)));


来源:https://stackoverflow.com/questions/46845461/ramda-to-loop-over-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!