shape-collection
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -80,6 +80,2 @@ /******/ (function(modules) { // webpackBootstrap | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
@@ -120,2 +116,11 @@ | ||
/** | ||
* @description Is function | ||
* @param val | ||
* @returns {boolean} | ||
*/ | ||
var isFunc = function isFunc(val) { | ||
return typeof val === 'function'; | ||
}; | ||
/** | ||
* @description Check if value is of type 'object' | ||
@@ -168,7 +173,7 @@ * @param val | ||
* @param obj | ||
* @param keysText | ||
* @param key | ||
* @returns {*} | ||
*/ | ||
var extractNestedProp = function extractNestedProp(obj, keysText) { | ||
var keys = keysText.split('.'); | ||
var extractNestedProp = function extractNestedProp(obj, key) { | ||
var keys = key.split('.'); | ||
var keysLength = keys.length - 1; | ||
@@ -206,10 +211,10 @@ var keysIndex = 0; | ||
* @param items | ||
* @param keysText | ||
* @param key | ||
* @param propType | ||
* @param direction | ||
*/ | ||
var _sortBy = function _sortBy(items, keysText, propType, direction) { | ||
var _sortBy = function _sortBy(items, key, propType, direction) { | ||
return items.sort(function (a, b) { | ||
var aVal = isStr(keysText) ? extractNestedProp(a, keysText) : ''; | ||
var bVal = isStr(keysText) ? extractNestedProp(b, keysText) : ''; | ||
var aVal = isStr(key) ? extractNestedProp(a, key) : ''; | ||
var bVal = isStr(key) ? extractNestedProp(b, key) : ''; | ||
@@ -243,6 +248,6 @@ if (isUndef(aVal) || isNull(aVal)) { | ||
} else if (propType === 'combo') { | ||
aVal = keysText.map(function (key) { | ||
aVal = key.map(function (key) { | ||
return extractNestedProp(a, key); | ||
}).join(' '); | ||
bVal = keysText.map(function (key) { | ||
bVal = key.map(function (key) { | ||
return extractNestedProp(b, key); | ||
@@ -322,3 +327,3 @@ }).join(' '); | ||
*/ | ||
var shape = exports.shape = function shape(items) { | ||
var shape = function shape(items) { | ||
var shapeItems = [].concat(_toConsumableArray(items)); | ||
@@ -338,4 +343,3 @@ | ||
filterByDuplicate: function filterByDuplicate(key) { | ||
var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; | ||
var length = 2; | ||
shapeItems = _filterByDuplicate(shapeItems, key, length); | ||
@@ -357,9 +361,29 @@ return this; | ||
}, | ||
reduceTo: function reduceTo(key) { | ||
reduceTo: function reduceTo(key, augmenter) { | ||
var hasAugmenter = isFunc(augmenter); | ||
shapeItems = shapeItems.reduce(function (accumulator, item) { | ||
var prop = extractNestedProp(item, key); | ||
var augmentObj = void 0; | ||
if (isFunc(augmenter)) { | ||
augmentObj = augmenter(item, prop, key); | ||
} | ||
if (isArr(prop)) { | ||
return [].concat(_toConsumableArray(accumulator), _toConsumableArray(prop)); | ||
var nextProp = prop; | ||
if (isObj(prop[0]) && hasAugmenter) { | ||
nextProp = prop.map(function (propItem) { | ||
return extend({}, propItem, isObj(augmentObj) ? augmentObj : {}); | ||
}); | ||
} | ||
return [].concat(_toConsumableArray(accumulator), _toConsumableArray(nextProp)); | ||
} else if (!isUndef(prop) && !isNull(prop)) { | ||
return [].concat(_toConsumableArray(accumulator), [prop]); | ||
var _nextProp = prop; | ||
if (isObj(prop) && hasAugmenter) { | ||
_nextProp = extend({}, prop, isObj(augmentObj) ? augmentObj : {}); | ||
} | ||
return [].concat(_toConsumableArray(accumulator), [_nextProp]); | ||
} | ||
@@ -373,3 +397,5 @@ return accumulator; | ||
module.exports = { shape: shape, extractNestedProp: extractNestedProp }; | ||
/***/ }) | ||
/******/ ]); |
@@ -1,1 +0,1 @@ | ||
!function(n){function t(e){if(r[e])return r[e].exports;var o=r[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var r={};t.m=n,t.c=r,t.d=function(n,r,e){t.o(n,r)||Object.defineProperty(n,r,{configurable:!1,enumerable:!0,get:e})},t.n=function(n){var r=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(r,"a",r),r},t.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},t.p="",t(t.s=0)}([function(n,t,r){n.exports=r(1)},function(n,t,r){"use strict";function e(n){if(Array.isArray(n)){for(var t=0,r=Array(n.length);t<n.length;t++)r[t]=n[t];return r}return Array.from(n)}Object.defineProperty(t,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n},u=function(n,t){Object.keys(n).forEach(function(r,e){return t(n[r],r,e)})},i=function(){var n=arguments[0],t=Object.assign(n,{}),r=[];return u(arguments,function(n,t,e){e>0&&r.push(n)}),r.forEach(function(n){Object.assign(t,n)}),t},c=function(n){return"object"===(void 0===n?"undefined":o(n))&&!a(n)&&!f(n)},f=function(n){return null===n},a=function(n){return Array.isArray(n)},s=function(n){return"string"==typeof n},l=function(n){return void 0===n},y=function(n,t){var r=t.split("."),e=r.length-1,o=0,u=!0,i=Object.assign({},n),a=void 0,s=void 0;if(r.length>0)for(;u;){if(s=i[r[o]],o===e){a=l(s)||f(s)?void 0:s;break}if(!c(s)){u=!1;break}i=s,o++}return a},p=function(n,t,r,e){return n.sort(function(n,o){var u=s(t)?y(n,t):"",i=s(t)?y(o,t):"";return l(u)||f(u)?"asc"===e?-1:1:l(i)||f(i)?"asc"===e?1:-1:"string"===r||"email"===r?u.toLowerCase()>i.toLowerCase()?"asc"===e?1:-1:u.toLowerCase()<i.toLowerCase()?"asc"===e?-1:1:0:"number"===r||"integer"===r||"float"===r?u>i?"asc"===e?1:-1:u<i?"asc"===e?-1:1:0:"date"===r?"asc"===e?new Date(u)-new Date(i):new Date(i)-new Date(u):"combo"===r?(u=t.map(function(t){return y(n,t)}).join(" "),i=t.map(function(n){return y(o,n)}).join(" "),l(u)||f(u)?"asc"===e?-1:1:l(i)||f(i)?"asc"===e?1:-1:u.toLowerCase()>i.toLowerCase()?"asc"===e?1:-1:u.toLowerCase()<i.toLowerCase()?"asc"===e?-1:1:0):void 0})},v=function(n,t){return n.reduce(function(n,r){var e=y(r,t);if(n.filter(function(n){return y(n,t)===e}).length>0)return n;var o=i({},r);return n.push(o),n},[])},d=function(n,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2;return n.filter(function(e){var o=y(e,t),u=r-1;return n.filter(function(n){return y(n,t)===o}).length>u})};t.shape=function(n){var t=[].concat(e(n));return{fetch:function(){return t},fetchIndex:function(n){return t[n]},filterByUnique:function(n){return t=v(t,n),this},filterByDuplicate:function(n){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return t=d(t,n,r),this},filterByProp:function(n,r){return t=t.filter(function(t){return y(t,n)===r}),this},sortBy:function(n){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"string",e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"asc";return t=p(t,n,r,e),this},reduceTo:function(n){return t=t.reduce(function(t,r){var o=y(r,n);return a(o)?[].concat(e(t),e(o)):l(o)||f(o)?t:[].concat(e(t),[o])},[]),this}}}}]); | ||
!function(t){function n(e){if(r[e])return r[e].exports;var o=r[e]={i:e,l:!1,exports:{}};return t[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r={};n.m=t,n.c=r,n.d=function(t,r,e){n.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:e})},n.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(r,"a",r),r},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=0)}([function(t,n,r){t.exports=r(1)},function(t,n,r){"use strict";function e(t){if(Array.isArray(t)){for(var n=0,r=Array(t.length);n<t.length;n++)r[n]=t[n];return r}return Array.from(t)}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},u=function(t,n){Object.keys(t).forEach(function(r,e){return n(t[r],r,e)})},i=function(){var t=arguments[0],n=Object.assign(t,{}),r=[];return u(arguments,function(t,n,e){e>0&&r.push(t)}),r.forEach(function(t){Object.assign(n,t)}),n},c=function(t){return"function"==typeof t},f=function(t){return"object"===(void 0===t?"undefined":o(t))&&!s(t)&&!a(t)},a=function(t){return null===t},s=function(t){return Array.isArray(t)},l=function(t){return"string"==typeof t},p=function(t){return void 0===t},y=function(t,n){var r=n.split("."),e=r.length-1,o=0,u=!0,i=Object.assign({},t),c=void 0,s=void 0;if(r.length>0)for(;u;){if(s=i[r[o]],o===e){c=p(s)||a(s)?void 0:s;break}if(!f(s)){u=!1;break}i=s,o++}return c},v=function(t,n,r,e){return t.sort(function(t,o){var u=l(n)?y(t,n):"",i=l(n)?y(o,n):"";return p(u)||a(u)?"asc"===e?-1:1:p(i)||a(i)?"asc"===e?1:-1:"string"===r||"email"===r?u.toLowerCase()>i.toLowerCase()?"asc"===e?1:-1:u.toLowerCase()<i.toLowerCase()?"asc"===e?-1:1:0:"number"===r||"integer"===r||"float"===r?u>i?"asc"===e?1:-1:u<i?"asc"===e?-1:1:0:"date"===r?"asc"===e?new Date(u)-new Date(i):new Date(i)-new Date(u):"combo"===r?(u=n.map(function(n){return y(t,n)}).join(" "),i=n.map(function(t){return y(o,t)}).join(" "),p(u)||a(u)?"asc"===e?-1:1:p(i)||a(i)?"asc"===e?1:-1:u.toLowerCase()>i.toLowerCase()?"asc"===e?1:-1:u.toLowerCase()<i.toLowerCase()?"asc"===e?-1:1:0):void 0})},d=function(t,n){return t.reduce(function(t,r){var e=y(r,n);if(t.filter(function(t){return y(t,n)===e}).length>0)return t;var o=i({},r);return t.push(o),t},[])},h=function(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2;return t.filter(function(e){var o=y(e,n),u=r-1;return t.filter(function(t){return y(t,n)===o}).length>u})},b=function(t){var n=[].concat(e(t));return{fetch:function(){return n},fetchIndex:function(t){return n[t]},filterByUnique:function(t){return n=d(n,t),this},filterByDuplicate:function(t){return n=h(n,t,2),this},filterByProp:function(t,r){return n=n.filter(function(n){return y(n,t)===r}),this},sortBy:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"string",e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"asc";return n=v(n,t,r,e),this},reduceTo:function(t,r){var o=c(r);return n=n.reduce(function(n,u){var l=y(u,t),v=void 0;if(c(r)&&(v=r(u,l,t)),s(l)){var d=l;return f(l[0])&&o&&(d=l.map(function(t){return i({},t,f(v)?v:{})})),[].concat(e(n),e(d))}if(!p(l)&&!a(l)){var h=l;return f(l)&&o&&(h=i({},l,f(v)?v:{})),[].concat(e(n),[h])}return n},[]),this}}};t.exports={shape:b,extractNestedProp:y}}]); |
56
index.js
@@ -30,2 +30,9 @@ /** | ||
/** | ||
* @description Is function | ||
* @param val | ||
* @returns {boolean} | ||
*/ | ||
const isFunc = val => typeof val === 'function'; | ||
/** | ||
* @description Check if value is of type 'object' | ||
@@ -68,7 +75,7 @@ * @param val | ||
* @param obj | ||
* @param keysText | ||
* @param key | ||
* @returns {*} | ||
*/ | ||
const extractNestedProp = (obj, keysText) => { | ||
const keys = keysText.split('.'); | ||
const extractNestedProp = (obj, key) => { | ||
const keys = key.split('.'); | ||
const keysLength = keys.length - 1; | ||
@@ -106,10 +113,10 @@ let keysIndex = 0; | ||
* @param items | ||
* @param keysText | ||
* @param key | ||
* @param propType | ||
* @param direction | ||
*/ | ||
const sortBy = (items, keysText, propType, direction) => { | ||
const sortBy = (items, key, propType, direction) => { | ||
return items.sort((a, b) => { | ||
let aVal = isStr(keysText) ? extractNestedProp(a, keysText) : ''; | ||
let bVal = isStr(keysText) ? extractNestedProp(b, keysText) : ''; | ||
let aVal = isStr(key) ? extractNestedProp(a, key) : ''; | ||
let bVal = isStr(key) ? extractNestedProp(b, key) : ''; | ||
@@ -145,4 +152,4 @@ if (isUndef(aVal) || isNull(aVal)) { | ||
} else if (propType === 'combo') { | ||
aVal = keysText.map(key => extractNestedProp(a, key)).join(' '); | ||
bVal = keysText.map(key => extractNestedProp(b, key)).join(' '); | ||
aVal = key.map(key => extractNestedProp(a, key)).join(' '); | ||
bVal = key.map(key => extractNestedProp(b, key)).join(' '); | ||
@@ -215,3 +222,3 @@ if (isUndef(aVal) || isNull(aVal)) { | ||
*/ | ||
export const shape = items => { | ||
const shape = items => { | ||
let shapeItems = [...items]; | ||
@@ -228,3 +235,4 @@ | ||
}, | ||
filterByDuplicate(key, length = 2) { | ||
filterByDuplicate(key) { | ||
const length = 2; | ||
shapeItems = filterByDuplicate(shapeItems, key, length); | ||
@@ -241,9 +249,27 @@ return this; | ||
}, | ||
reduceTo(key) { | ||
reduceTo(key, augmenter) { | ||
const hasAugmenter = isFunc(augmenter); | ||
shapeItems = shapeItems.reduce((accumulator, item) => { | ||
const prop = extractNestedProp(item, key); | ||
let augmentObj; | ||
if (isFunc(augmenter)) { | ||
augmentObj = augmenter(item, prop, key); | ||
} | ||
if (isArr(prop)) { | ||
return [...accumulator, ...prop]; | ||
let nextProp = prop; | ||
if (isObj(prop[0]) && hasAugmenter) { | ||
nextProp = prop.map(propItem => extend({}, propItem, isObj(augmentObj) ? augmentObj : {})) | ||
} | ||
return [...accumulator, ...nextProp]; | ||
} else if (!isUndef(prop) && !isNull(prop)) { | ||
return [...accumulator, prop]; | ||
let nextProp = prop; | ||
if (isObj(prop) && hasAugmenter) { | ||
nextProp = extend({}, prop, isObj(augmentObj) ? augmentObj : {}); | ||
} | ||
return [...accumulator, nextProp]; | ||
} | ||
@@ -256,1 +282,3 @@ return accumulator; | ||
}; | ||
module.exports = { shape, extractNestedProp }; |
{ | ||
"name": "shape-collection", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "Utility for manipulating data in arrays of objects", | ||
@@ -5,0 +5,0 @@ "main": "input.js", |
173
README.md
@@ -43,15 +43,16 @@ <!-- Name --> | ||
## API | ||
## Shape API | ||
All methods available under the `shape` API, morph data into arrays. To retrieve the morphed array, call `fetch()` at the end of your sequence. Then, you can take full advantage of `array-extras` methods like `map`, `sort` and `filter`. All methods, which accept `key` as property, support nested key look-ups like `user.details.createdAt`. This works for nested object properties only. | ||
### fetch | ||
`Function`. Returns the shaped collection. | ||
`Function`. Returns the morphed collection. | ||
### fetchIndex(index) | ||
`Function`. Returns item at a specific index from the shaped collection. | ||
`Function`. Returns item at a specific index from the morphed collection. | ||
### filterByUnique(key, value) | ||
### filterByUnique(key) | ||
`Function`. Filters the collection by unique value: | ||
`Function`. Filters the collection by unique values for given key: | ||
@@ -67,14 +68,22 @@ ```javascript | ||
users: ['kk', 'zz', 'xyz'] | ||
}, { | ||
id: 1, | ||
users: ['aa', 'bb'] | ||
}, { | ||
id: 2, | ||
users: ['kk', 'zz', 'xyz'] | ||
}]; | ||
const user = shape(arr).filterByUnique('id', 1).fetchIndex(0); | ||
const uniqueItems = shape(arr).filterByUnique('id').fetch(); | ||
// user contains: | ||
// {id: 1, users: ['aa', 'bb']} | ||
// uniqueItems contains: | ||
// [{ id: 1, users: ['aa', 'bb'] }, { id: 2, users: ['kk', 'zz', 'xyz'] }] | ||
``` | ||
### filterByDuplicate(key, length = 2) | ||
This function filters by first found unique value. All subsequent identical values are ignored. | ||
`Function`. Filter and extract duplicate items from collection: | ||
### filterByDuplicate(key) | ||
`Function`. Filter the collection by duplicate values for given key: | ||
```javascript | ||
@@ -89,3 +98,3 @@ const arr = [{ | ||
users: ['kk', 'zz', 'xyz'] | ||
}, , { | ||
}, { | ||
id: 3, | ||
@@ -104,3 +113,3 @@ type: 'a', | ||
`Function`. Filter collection by property value: | ||
`Function`. Filter collection by key-value pair comparison: | ||
@@ -116,3 +125,3 @@ ```javascript | ||
users: ['kk', 'zz', 'xyz'] | ||
}, , { | ||
}, { | ||
id: 3, | ||
@@ -142,3 +151,3 @@ type: 'a', | ||
users: ['kk', 'zz', 'xyz'] | ||
}, , { | ||
}, { | ||
id: 3, | ||
@@ -171,3 +180,3 @@ type: 'a', | ||
### reduceTo(key) | ||
### reduceTo(key, augmenter = (item, prop, key) => {}) | ||
@@ -197,2 +206,79 @@ `Function`. Reduce collection to another collection: | ||
You can also pass an optional `augmenter` function to `reduceTo` as a second argument. An augmenter is a special function, invoked only when you are reducing arrays of objects to another array of objects. It can be useful, when you want to extract a nested array of objects but also want to keep track of their parent objects after they have been reduced. Here's an example: | ||
```javascript | ||
const users = [{ | ||
id: 1, | ||
type: 'day_group', | ||
grades: { | ||
english: 4, | ||
driving: 7 | ||
} | ||
}, { | ||
id: 2, | ||
type: 'evening_group', | ||
grades: { | ||
english: 6, | ||
driving: 10 | ||
} | ||
}, { | ||
id: 3, | ||
type: 'weekend_group', | ||
grades: [] | ||
}]; | ||
const gradesWithUserId = shape(users) | ||
.reduceTo('grades', ({ id }) => ({ id })) | ||
.fetch(); | ||
// gradesWithUserId contains | ||
/* | ||
[ | ||
{ english: 4, driving: 7, id: 1 }, | ||
{ english: 6, driving: 10, id: 2 } | ||
] | ||
``` | ||
The `augmenter` method returns an object, which is then merged into the respective reduced item. With an augmenter you can add identifiers to your morphed collections. | ||
The following params are passed to `augmenter`: | ||
- item - the parent item | ||
- prop - the currently reduced-to item | ||
- key - key passed to the `reduceTo` function | ||
## extractNestedProp | ||
A helper utility method for retrieving object properties at any level. | ||
```javascript | ||
import { extractNestedProp } from 'shape-collection'; | ||
const users = [{ | ||
id: 1, | ||
type: 'day_group', | ||
grades: { | ||
english: 4, | ||
driving: 7 | ||
} | ||
}, { | ||
id: 2, | ||
type: 'evening_group', | ||
grades: { | ||
english: 6, | ||
driving: 10 | ||
} | ||
}, { | ||
id: 3, | ||
type: 'weekend_group', | ||
grades: [] | ||
}]; | ||
const [ firstUser ] = users; | ||
const englishGrade = extractNestedProp(firstUser, 'grades.english'); | ||
// englishGrade contains | ||
// 4 | ||
``` | ||
`extractNestedProp` works on any level as long as the prop at the requested key is an object. For multiple keys like `grades.english` this means that grades must be an object. This methods returns `undefined` if no such key exists in the target object. | ||
## Examples | ||
@@ -334,2 +420,59 @@ | ||
*/ | ||
const nestedItems = [{ | ||
id: 1, | ||
type: 'a', | ||
items: [{ | ||
id: 11, | ||
type: 'aa', | ||
items: [{ | ||
id: 111, | ||
type: 'aaa', | ||
items: [{ | ||
id: 1111, | ||
type: 'aaaa' | ||
}] | ||
}] | ||
}] | ||
}, { | ||
id: 2, | ||
type: 'b', | ||
items: [{ | ||
id: 22, | ||
type: 'bb', | ||
items: [{ | ||
id: 222, | ||
type: 'bbb', | ||
items: [{ | ||
id: 2222, | ||
type: 'bbbb' | ||
}] | ||
}] | ||
}] | ||
}, { | ||
id: 3, | ||
type: 'c', | ||
items: [{ | ||
id: 33, | ||
type: 'cc', | ||
items: [{ | ||
id: 333, | ||
type: 'ccc' | ||
}] | ||
}] | ||
}]; | ||
const nestedItems = shape(nestedItems) | ||
.reduceTo('items') | ||
.reduceTo('items') | ||
.reduceTo('items') | ||
.fetch(); | ||
// nestedItems contains: | ||
/* | ||
[ | ||
{id: 1111, type: "aaaa"}, | ||
{id: 2222, type: "bbbb"} | ||
] | ||
*/ | ||
``` |
@@ -18,2 +18,5 @@ export const groups = [{ | ||
age: 33, | ||
calendar: { | ||
birthday: '12/12/1986' | ||
}, | ||
exams: [{ | ||
@@ -104,1 +107,66 @@ name: 'English B1', | ||
}]; | ||
export const advancedUsers = [{ | ||
id: 1, | ||
type: 'day_group', | ||
grades: [{ | ||
english: 4, | ||
driving: 7 | ||
}, { | ||
spanish: 5, | ||
programming: 6 | ||
}] | ||
}, { | ||
id: 2, | ||
type: 'evening_group', | ||
grades: [{ | ||
english: 6, | ||
driving: 10 | ||
}, { | ||
spanish: 10, | ||
programming: 10 | ||
}] | ||
}]; | ||
export const nestedItems = [{ | ||
id: 1, | ||
type: 'a', | ||
items: [{ | ||
id: 11, | ||
type: 'aa', | ||
items: [{ | ||
id: 111, | ||
type: 'aaa', | ||
items: [{ | ||
id: 1111, | ||
type: 'aaaa' | ||
}] | ||
}] | ||
}] | ||
}, { | ||
id: 2, | ||
type: 'b', | ||
items: [{ | ||
id: 22, | ||
type: 'bb', | ||
items: [{ | ||
id: 222, | ||
type: 'bbb', | ||
items: [{ | ||
id: 2222, | ||
type: 'bbbb' | ||
}] | ||
}] | ||
}] | ||
}, { | ||
id: 3, | ||
type: 'c', | ||
items: [{ | ||
id: 33, | ||
type: 'cc', | ||
items: [{ | ||
id: 333, | ||
type: 'ccc' | ||
}] | ||
}] | ||
}]; |
40745
799
470