नोड.जेएस में ऑब्जेक्ट कुंजियों पर Iterate करें


139

जावास्क्रिप्ट 1.7 के बाद से एक Iterator ऑब्जेक्ट है, जो इसे अनुमति देता है:

var a={a:1,b:2,c:3};
var it=Iterator(a);

function iterate(){
    try {  
        console.log(it.next());
        setTimeout(iterate,1000);
    }catch (err if err instanceof StopIteration) {  
        console.log("End of record.\n");  
    } catch (err) {  
        console.log("Unknown error: " + err.description + "\n");  
    }  

}
iterate();

वहाँ नोड में इस तरह से कुछ है। जेएस?

अभी मैं उपयोग कर रहा हूँ:

function Iterator(o){
    /*var k=[];
    for(var i in o){
        k.push(i);
    }*/
    var k=Object.keys(o);
    return {
        next:function(){
            return k.shift();
        }
    };
}

लेकिन वह सभी ऑब्जेक्ट कुंजियों को संग्रहीत करके बहुत अधिक ओवरहेड बनाता है k


आप यह देखा है? ejohn.org/blog/unimpressed-by-nodeiterator
jcolebrand

2
क्या उपरि? आपके पास कितनी चाबियां और चलने वाले हैं? यदि उनका उत्पाद 1 मिलियन से कम है, तो बस इस 'अक्षमता' को अनदेखा करें।
c69

@jcolebrand φ: ऐसा लगता createNodeIteratorहै कि DOM तत्वों के लिए है, मेरे पास DOM भी नहीं है;) @ c69: मैं keysऑब्जेक्ट के सभी डेटा को स्टोर करता हूं और valueबस 1(700k कीज़ में लगभग 20MB) सेट किया जाता है , वास्तव में, के लिए अब मैं सिर्फ इस 'उपरि' की अनदेखी कर रहा हूं, लेकिन मैं एक बेहतर समाधान पसंद करूंगा :)
स्टू

मैंने इसे एक वर्ग के रूप में देखा है ;-)
jcolebrand

जवाबों:


246

आप जो चाहते हैं वह एक वस्तु या सरणी पर आलसी पुनरावृत्ति है। यह ES5 में संभव नहीं है (इस प्रकार नोड में संभव नहीं है। जेएस)। हम इसे अंततः प्राप्त करेंगे।

एकमात्र समाधान एक नोड मॉड्यूल ढूंढ रहा है जो पुनरावृत्तियों (और शायद जनरेटर) को लागू करने के लिए वी 8 का विस्तार करता है। मुझे कोई कार्यान्वयन नहीं मिला। आप spidermonkey स्रोत कोड को देख सकते हैं और इसे C ++ में V8 एक्सटेंशन के रूप में लिखने का प्रयास कर सकते हैं।

आप निम्नलिखित कोशिश कर सकते हैं, हालांकि यह सभी कुंजी को मेमोरी में लोड करेगा

Object.keys(o).forEach(function(key) {
  var val = o[key];
  logic();
});

हालाँकि, चूंकि Object.keysयह एक देशी तरीका है जिससे यह बेहतर अनुकूलन की अनुमति दे सकता है

बेंचमार्क

जैसा कि आप देख सकते हैं Object.keys काफी तेज है। वास्तविक मेमोरी स्टोरेज अधिक इष्टतम है या नहीं यह अलग बात है।

var async = {};
async.forEach = function(o, cb) {
  var counter = 0,
    keys = Object.keys(o),
    len = keys.length;
  var next = function() {
    if (counter < len) cb(o[keys[counter++]], next);
  };
  next();
};

async.forEach(obj, function(val, next) {
  // do things
  setTimeout(next, 100);
});

धन्यवाद!, यह मेरे forEachपुनरावृत्त को थोड़ा सुधारता है :) (कोड को अद्यतन किया गया है) लेकिन दुख की बात है कि स्मृति मुद्दा बनी हुई है :( और मैं उपयोग नहीं कर सकता क्योंकि प्रत्येक पुनरावृत्ति कदम को एक async से आह्वान किया जाना चाहिए setTimeout
stewe

@stewe ने एकasync.forEach
Raynos

सफाई देने के लिए धन्यवाद! मैं शायद c ++ एक्सटेंशन दृष्टिकोण की कोशिश करूंगा।
स्टू

2
@stewe यदि आप इसे लिखने का प्रबंधन करते हैं, तो इसे github पर प्रकाशित करें और यहां एक उत्तर में एक लिंक छोड़ दें या एक टिप्पणी ओ /
Raynos

@ उस C ++ एक्सटेंशन के बारे में, क्या आपने इसे लेखक किया है?
रेयोनोस

22

यह भी याद रखें कि आप .forEach()फ़ंक्शन का दूसरा तर्क पास कर सकते हैं जो ऑब्जेक्ट को thisकीवर्ड के रूप में उपयोग करने के लिए निर्दिष्ट करता है ।

// myOjbect is the object you want to iterate.
// Notice the second argument (secondArg) we passed to .forEach.
Object.keys(myObject).forEach(function(element, key, _array) {
  // element is the name of the key.
  // key is just a numerical value for the array
  // _array is the array of all the keys

  // this keyword = secondArg
  this.foo;
  this.bar();
}, secondArg);

5
धागे के अलावा अच्छा है, लेकिन ... क्यों पृथ्वी पर वस्तु को "तत्व" नामक चीज की कुंजी के रूप में दिखाया गया है, और "सरणी" नामक कुंजी सरणी के लिए एन्यूमरेटर? क्या मैं सुझाव दे सकता हूं कि आप अपने कोड नमूने का उपयोग करने के लिए अपडेट करेंObject.keys(myObject).forEach(function(key, index, arrayOfKeys) {
एंडी लोरेन्ज

4

कुंजी / मानों के सरल पुनरावृत्ति के लिए, कभी-कभी अंडरस्कोरज जैसे पुस्तकालय आपके मित्र हो सकते हैं।

const _ = require('underscore');

_.each(a, function (value, key) {
    // handle
});

सिर्फ संदर्भ के लिए


इसने मेरे लिए काम किया। के बारे में नहीं जानते underscorejs। मैंने lodashलाइब्रेरी से इस फ़ंक्शन का उपयोग किया ।
नीरली आचार्य

3

मैं नोड.जेएस (लगभग 2 सप्ताह) के लिए नया हूं, लेकिन मैंने सिर्फ एक मॉड्यूल बनाया है जो किसी वस्तु की सामग्री को पुन: कंसोल को रिपोर्ट करता है। यह सभी को सूचीबद्ध करेगा या एक विशिष्ट वस्तु की खोज करेगा और फिर जरूरत पड़ने पर एक गहराई से नीचे ड्रिल करेगा।

शायद आप अपनी आवश्यकताओं को पूरा करने के लिए इसे अनुकूलित कर सकते हैं। इसे सरल रखें! क्यों उलझी? ...

'use strict';

//console.log("START: AFutils");

// Recusive console output report of an Object
// Use this as AFutils.reportObject(req, "", 1, 3); // To list all items in req object by 3 levels
// Use this as AFutils.reportObject(req, "headers", 1, 10); // To find "headers" item and then list by 10 levels
// yes, I'm OLD School!  I like to see the scope start AND end!!!  :-P
exports.reportObject = function(obj, key, level, deep) 
{
    if (!obj)
    { 
        return;
    }

    var nextLevel = level + 1;

    var keys, typer, prop;
    if(key != "")
    {   // requested field
        keys = key.split(']').join('').split('[');
    }
    else
    {   // do for all
        keys = Object.keys(obj);
    }
    var len = keys.length;
    var add = "";
    for(var j = 1; j < level; j++)
    {
        // I would normally do {add = add.substr(0, level)} of a precreated multi-tab [add] string here, but Sublime keeps replacing with spaces, even with the ["translate_tabs_to_spaces": false] setting!!! (angry)
        add += "\t";
    }

    for (var i = 0; i < len; i++) 
    {
        prop = obj[keys[i]];
        if(!prop)
        {
            // Don't show / waste of space in console window...
            //console.log(add + level + ": UNDEFINED [" + keys[i] + "]");
        }
        else
        {
            typer = typeof(prop);
            if(typer == "function")
            {
                // Don't bother showing fundtion code...
                console.log(add + level + ": [" + keys[i] + "] = {" + typer + "}");
            }
            else
            if(typer == "object")
            {
                console.log(add + level + ": [" + keys[i] + "] = {" + typer + "}");
                if(nextLevel <= deep)
                {
                    // drop the key search mechanism if first level item has been found...
                    this.reportObject(prop, "", nextLevel, deep); // Recurse into
                }
            }
            else
            {
                // Basic report
                console.log(add + level + ": [" + keys[i] + "] = {" + typer + "} = " + prop + ".");
            }
        }
    }
    return ;
};

//console.log("END: AFutils");

0

उसका कोड समायोजित करें:

Object.prototype.each = function(iterateFunc) {
        var counter = 0,
keys = Object.keys(this),
currentKey,
len = keys.length;
        var that = this;
        var next = function() {

            if (counter < len) {
                currentKey = keys[counter++];
                iterateFunc(currentKey, that[currentKey]);

                next();
            } else {
                that = counter = keys = currentKey = len = next = undefined;
            }
        };
        next();
    };

    ({ property1: 'sdsfs', property2: 'chat' }).each(function(key, val) {
        // do things
        console.log(key);
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.