2016-04-06 4 views
6

У меня есть массив объектов в формате ниже:конденсацию объект массива рекурсивно в JavaScript

{ 
    "country": "India", 
    "children": [ 
    { 
     "name": "Karnataka", 
     "type": "State", 
     "children": [ 
     { 
      "name": "", 
      "type": "city" 
     }, 
     { 
      "name": "Bangalore", 
      "type": "city" 
     }, 
     { 
      "name": "Mangalore", 
      "type": "city" 
     } 
     ] 
    }, 
    { 
     "name": "Kerala", 
     "type": "State", 
     "children": [ 
     { 
      "name": "", 
      "type": "city" 
     } 
     ] 
    }, 
    { 
     "name": "Maharashtra", 
     "type": "State", 
     "children": [ 
     { 
      "name": "Mumbai", 
      "type": "city" 
     }, 
     { 
      "name": "Pune", 
      "type": "city" 
     } 
     ] 
    } 
    ] 
} 

Каждый объект имеет элемент детей, который содержит детали элемента. Мне нужно рекурсивно перебирать объект json и удалять все узлы, name - пустая строка до корня. Для приведенного выше формата JSON, вывод должен быть, как показано ниже:

{ 
    "country": "India", 
    "children": [ 
    { 
     "name": "Karnataka", 
     "type": "State", 
     "children": [ 
     { 
      "name": "Bangalore", 
      "type": "city" 
     }, 
     { 
      "name": "Mangalore", 
      "type": "city" 
     } 
     ] 
    }, 
    { 
     "name": "Kerala", 
     "type": "State", 
     "children": [ 
     ] 
    }, 
    { 
     "name": "Maharastra", 
     "type": "State", 
     "children": [ 
     { 
      "name": "Mumbai", 
      "type": "city" 
     }, 
     { 
      "name": "Pune", 
      "type": "city" 
     } 
     ] 
    } 
    ] 
} 

Как это сделать в JavaScript рекурсивно с помощью Underscorejs.

+0

'Array # map' ..? – Rayon

+0

@ RayonDabre-мне кажется * reduceRight * и удалять нежелательные участники лучше, но у underscore.js есть что? Если нет, есть встроенный. – RobG

+0

[Этот вопрос SO] (http://stackoverflow.com/questions/36171667/find-and-remove-empty-properties-from-objects/36171824) может помочь вам – Aides

ответ

3

Это рекурсивная раствор с Array#filter().

function filterName(a) { 
 
    if (a.name) { 
 
     if (Array.isArray(a.children)) { 
 
      a.children = a.children.filter(filterName); 
 
     } 
 
     return true; 
 
    } 
 
} 
 

 
var object = { "country": "India", "children": [{ "name": "Karnataka", "type": "State", "children": [{ "name": "", "type": "city" }, { "name": "Bangalore", "type": "city" }, { "name": "Mangalore", "type": "city" }] }, { "name": "Kerala", "type": "State", "children": [{ "name": "", "type": "city" }] }, { "name": "Maharashtra", "type": "State", "children": [{ "name": "Mumbai", "type": "city" }, { "name": "Pune", "type": "city" }] }] }; 
 

 
object.children.forEach(filterName); 
 
document.write("<pre>" + JSON.stringify(object, 0, 4) + "</pre>");

1

Попробуйте это:

function condense(arr) { 

    arr.children = arr.children.map(function(c) { 
    c.children = c.children.filter(function(c1) { 
     return c1.name; 
    }); 
    return c; 
    }); 

    return arr; 
} 

Я перебирать детей (с map), затем процеживают массив детей с filter. Будут сохранены только дети с именем, не имеющим нулевой или пустой.

Адрес jsfiddle.

+0

Я пробовал аналогичный подход. Я хотел попробовать это с рекурсией. – zilcuanu

+0

Почему? У вас есть только два уровня глубины. Кроме того, на первом уровне вы держите пустых детей, а во втором - их удаляете. Это не похоже на хорошего кандидата в рекурсию. – Derlin

1

au fait с underscore.js. Вы можете сделать это с помощью ES5 reduceRight и удалить участников, которых вы не хотите, он должен быть более эффективным, чем другие подходы. Следующий использует рекурсию (который не является столь же эффективным, как последовательной обработке, но, скорее всего, меньше кода), так что вы можете гнездятся объекты, как глубокие, как вам нравится:

function removeEmpty(obj) { 
 
    obj.children.reduceRight(function (acc, child, i) { 
 
    if (!child.name) { 
 
     obj.children.splice(i, 1); 
 
    } else if (child.children) { 
 
     removeEmpty(child); 
 
    } 
 
    return null; 
 
    }, null); 
 
    return obj; 
 
} 
 

 
// Test 
 
var data = { 
 
    "country": "India", 
 
    "children": [ 
 
    { 
 
     "name": "Karnataka", 
 
     "type": "State", 
 
     "children": [ 
 
     { 
 
      "name": "", 
 
      "type": "city" 
 
     }, 
 
     { 
 
      "name": "Bangalore", 
 
      "type": "city" 
 
     }, 
 
     { 
 
      "name": "Mangalore", 
 
      "type": "city" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "name": "Kerala", 
 
     "type": "State", 
 
     "children": [ 
 
     { 
 
      "name": "", 
 
      "type": "city" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "name": "Maharashtra", 
 
     "type": "State", 
 
     "children": [ 
 
     { 
 
      "name": "Mumbai", 
 
      "type": "city" 
 
     }, 
 
     { 
 
      "name": "Pune", 
 
      "type": "city" 
 
     } 
 
     ] 
 
    } 
 
    ] 
 
} 
 

 

 
document.write('Original:<br>' + JSON.stringify(data) + '<br><br>' + 
 
       'Modified:<br>' + JSON.stringify(removeEmpty(data)));

+0

О, использование 'reduceRight' настолько запутанно здесь, поскольку вы ничего не уменьшаете ... – Bergi

+0

Да, это просто итерация от длины до 0, аккумулятор игнорируется. Возможно, должен быть * forEachRight *? ;-) Думая об этом сейчас, * return null * можно опустить. – RobG

+0

Возможно, также '_' вместо' acc' – Bergi

1

Это очень специфичные для вашего примера.

Link to fiddle

var obj = { 
 
    "country": "India", 
 
    "children": [{ 
 
    "name": "Karnataka", 
 
    "type": "State", 
 
    "children": [{ 
 
     "name": "", 
 
     "type": "city" 
 
    }, { 
 
     "name": "Bangalore", 
 
     "type": "city" 
 
    }, { 
 
     "name": "Mangalore", 
 
     "type": "city" 
 
    }] 
 
    }, { 
 
    "name": "Kerala", 
 
    "type": "State", 
 
    "children": [{ 
 
     "name": "", 
 
     "type": "city" 
 
    }] 
 
    }, { 
 
    "name": "Maharashtra", 
 
    "type": "State", 
 
    "children": [{ 
 
     "name": "Mumbai", 
 
     "type": "city" 
 
    }, { 
 
     "name": "Pune", 
 
     "type": "city" 
 
    }] 
 
    }] 
 
}; 
 

 
//Before 
 
document.write("BEFORE: "+JSON.stringify(obj)); 
 
//After 
 
document.write("AFTER: "+JSON.stringify(checkJSON(obj))); 
 

 
function checkJSON(obj) { 
 
    $.each(obj.children, function(index, value) { 
 
    if ($.isArray(value.children)) { 
 
     $.each(value.children, function(index, value) { 
 
     if (value.name == '') { 
 
      delete value.name; 
 
     } 
 
     }); 
 
    } 
 
    }); 
 
    return obj; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

1

Наверное, не самый короткий путь, но это работает:

obj.children = _.each(obj.children, filter); 

function filter(child, index, arr) { 
    if (child && child.name === '') { 
    // remove the ones without name 
    arr.splice(index, 1); 

    } else if (_.has(child, 'children')) { 
    // remove nested children 
    child.children = _.each(child.children, filter); 

    // check for empty children array and remove it (if needed) 
    /* 
    if (child.children.length === 0) { 
     delete child['children']; 
    } 
    */ 
    } 

    return child; 
} 

Fiddle: https://jsfiddle.net/gnmosu5p/2/

1

Я знаю, что рекурсивный а, pproach спрашивается, но я не могу помочь себе дать один лайнер здесь.

var newData = JSON.parse(JSON.stringify(data).replace(/{"name":"".+?},?/g, "")); 

, где data является первоначально данный объект, чтобы быть перестроена.

Это несколько медленнее, чем функции массива, но одно из преимуществ этого метода заключается в сохранении исходного объекта данных, как и в случае, когда все методы массива переопределяют исходный объект данных, если вы его не клонируете.

Смежные вопросы