मुझे क्वेरी के आधार पर इस तरह दिखने वाली नेस्टेड संरचना को फ़िल्टर करने की आवश्यकता है। मुझे सबट्री के मूल ऑब्जेक्ट सहित सभी ऑब्जेक्ट्स को वापस करने की आवश्यकता है, जो ऑब्जेक्ट नाम में क्वेरी स्ट्रिंग से मेल खाते हैं। कृपया मदद करें, मैं फंस गया हूँ।

[
   {
     name: 'bob',
     type: 1,
     children: [
       {
         name: 'bob',
         type: 2,
         children: [
           {
             name: 'mike',
             type: 3,
             children: [ 
               {
                 name:'bob',
                 type: 7,
                 children: []
               },
               {
                 name: 'mike',
                 type: 9,
                 children: []
               }
             ]
           }
         ]
       },
       {
         name: 'mike',
         type: 2
       }
     ]
   }
 ]

अभी मैं पेड़ में एक मैच को दोबारा ढूंढने में सक्षम हूं, लेकिन फ़ंक्शन ऑब्जेक्ट को पहले मैच पर देता है और उसी ऑब्जेक्ट में उप स्तरों पर गहराई से खोज नहीं करता है। कोई सुझाव, मैं सभी स्तरों के माध्यम से पुनरावर्ती रूप से खोज करने के लिए कोड को कैसे संशोधित कर सकता हूं?

  return tree.map(copy).filter(function filterNested(node) {
    if (node.name.toLowerCase().indexOf(query) !== -1) {
      return true;
    }

    if (node.children) {
      return (node.children = node.children.map(copy).filter(filterNested))
        .length;
    }
  });

अगर मैं क्वेरी 'बॉब' खोज रहा हूं, तो अपेक्षित परिणाम होना चाहिए,

 const arr = [
   {
     name: 'bob',
     type: 1,
     children: [
       {
         name: 'bob',
         type: 2,
         children: [
           {
             name: 'mike',
             type: 3,
             children: [ 
               {
                 name:'bob',
                 type: 7
               },
  
             ]
           }
         ]
       },
     ]
   }
 ]

6
leonard0 29 अक्टूबर 2019, 23:51

5 जवाब

सबसे बढ़िया उत्तर

आप सरणी को कम कर सकते हैं और वैकल्पिक बच्चों के साथ नई वस्तुओं का निर्माण कर सकते हैं, यदि उनकी लंबाई शून्य नहीं है।

function filter(array, fn) {
    return array.reduce((r, o) => {
        var children = filter(o.children || [], fn);
        if (fn(o) || children.length) r.push(Object.assign({}, o, children.length && { children }));
        return r;
    }, []);
}

var data = [{ name: 'bob', type: 1, children: [{ name: 'bob', type: 2, children: [{ name: 'mike', type: 3, children: [{ name: 'bob', type: 7 }, { name: 'same', typ: 9 }] }] }, { name: 'mike', type: 2 }] }],
    result = filter(data, ({ name }) => name.toLowerCase() === 'bob');

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
3
Nina Scholz 29 अक्टूबर 2019, 21:52

मैं नए पेड़ को पार करने और बनाने के लिए बस अच्छे पुराने विज़िटर पैटर्न का उपयोग करूंगा।

class Visitor {
    constructor(predicate) {
        this.predicate = predicate;
    }

    visit(item) {
        if (Array.isArray(item)) {
            return this.visitArray(item);
        } else if (item) {
            return this.visitItem(item);
        }
    }

    visitArray(item) {
        const result = [];
        for (let e of item) {
            const item = this.visit(e);
            if (item) {
                result.push(item);
            }
        }
        return result;
    }

    visitItem(item) {
        const children = this.visit(item.children);
        const hasChildren = (children && children.length > 0);

        if (hasChildren || this.predicate(item)) {
            return {
                name: item.name,
                type: item.type,
                children: children
            }
        }
        return null;
    }
}


const visitor = new Visitor((item) => item.name === "bob");
const result = visitor.visit(data);

console.log(result);
1
Edin Omeragic 29 अक्टूबर 2019, 21:35

आप इसके लिए एक पुनरावर्ती कम का उपयोग कर सकते हैं, जहां आप जांचते हैं कि क्या कोई बच्चे हैं या यदि नाम वस्तु को जमा करने से पहले मेल खाता है:

const example = [{
  name: 'bob',
  type: 1,
  children: [{
      name: 'bob',
      type: 2,
      children: [{
        name: 'mike',
        type: 3,
        children: [{
            name: 'bob',
            type: 7,
            children: []
          },
          {
            name: 'mike',
            type: 9,
            children: []
          }
        ]
      }]
    },
    {
      name: 'mike',
      type: 2
    }
  ]
}];

function reduceName(accum, item, matcher) {
  item.children = (item.children || []).reduce((a,i)=>reduceName(a,i,matcher),[]);
  if (!item.children.length) delete item.children;
  if (matcher(item) || item.children) accum.push(item);
  return accum;
}

console.log(example.reduce((a,i)=>reduceName(a,i,x=>x.name==='bob'),[]));
1
Ruzihm 29 अक्टूबर 2019, 21:18

मुझे लगता है कि यह प्रश्न हमेशा प्रासंगिक रहेगा इसलिए मैंने यह कैसे किया! कुछ घंटों के बाद ;)

var res = yourArray.filter(function f(el) {
    if (el.children.length > 0) {
        el.children = el.childreb.filter(f);
    }
    if (el.name === "bob") return true; // you can put the condition you need here.
})
//res is your returned array

वास्तव में आशा है कि इस कोड से आप में से कुछ को लाभ होगा :)

0
Nathan Adda 8 जून 2020, 05:59

म्यूचुअल रिकर्सन और निरंतर गुजरने की शैली

const data =
  [{name:'bob',type:1,children:[{name:'bob',type:2,children:[{name:'mike',type:3,children:[ {name:'bob',type:7,children:[]},{name:'mike',type:9,children:[]}]}]},{name:'mike',type:2}]}]

const identity = x => x

const search = (all = [], query = identity, pass = identity) =>
  all.flatMap(v => search1(v, query, pass))

const search1 = (one = {}, query = identity, pass = identity) =>
  query(one)
    ? pass([ { ...one, children: search(one.children, query) } ])
    : search
        ( one.children
        , query
        , children =>
            children.length === 0
              ? pass([])
              : pass([ { ...one, children } ])
        )

const result =
  search(data, x => x.name === "bob")

console.log(JSON.stringify(result, null, 2))
1
Thank you 8 जून 2020, 15:26