سؤال

هل هناك نهج عام "ضغط" الكائنات المتداخلة إلى مستوى واحد:

var myObj = {
    a: "hello",
    b: {
        c: "world"
    }
}

compress(myObj) == {
    a: "hello",
    b_c: "world"
}

أعتقد أن هناك بعض العودية المعنية، لكنني أحسب أنني لست بحاجة إلى إعادة اختراع العجلة هنا ...!

هل كانت مفيدة؟

المحلول

function flatten(obj, includePrototype, into, prefix) {
    into = into || {};
    prefix = prefix || "";

    for (var k in obj) {
        if (includePrototype || obj.hasOwnProperty(k)) {
            var prop = obj[k];
            if (prop && typeof prop === "object" &&
                !(prop instanceof Date || prop instanceof RegExp)) {
                flatten(prop, includePrototype, into, prefix + k + "_");
            }
            else {
                into[prefix + k] = prop;
            }
        }
    }

    return into;
}

يمكنك تضمين الأعضاء الموروثين من خلال المرور true في المعلمة الثانية.

بعض التحذيرات:

  • الكائنات العودية لن تعمل. علي سبيل المثال:

    var o = { a: "foo" };
    o.b = o;
    flatten(o);
    

    سوف تابع حتى يلقي استثناء.

  • مثل إجابة Ruquay، تسحب هذا عناصر الصفيف تماما مثل خصائص الكائنات الطبيعية. إذا كنت ترغب في الحفاظ على صفائف سليمة، أضف "|| prop instanceof Array"للاستثناءات.

  • إذا اتصلت بهذا على الكائنات من نافذة أو إطار مختلف، فلن يتم تضمين التواريخ والتعبيرات العادية، منذ instanceof لن تعمل بشكل صحيح. يمكنك إصلاح ذلك عن طريق استبداله بطريقة Tostring الافتراضية مثل هذا:

    Object.prototype.toString.call(prop) === "[object Date]"
    Object.prototype.toString.call(prop) === "[object RegExp]"
    Object.prototype.toString.call(prop) === "[object Array]"
    

نصائح أخرى

إليك واحدة سريعة، ولكن احترس، B / C سوف ليس العمل W / المصفوفات والقيم الخالية (B / C إرجاع نوع "كائن").

var flatten = function(obj, prefix) {
  if(typeof prefix === "undefined") {
    prefix = "";
  }
  var copy = {};
  for (var p in obj) {
    if(obj.hasOwnProperty(p)) {
      if(typeof obj[p] === "object") {
        var tmp = flatten(obj[p], p + "_");
        for(var q in tmp) {
          if(tmp.hasOwnProperty(q)) {
            copy[prefix + q] = tmp[q];
          }
        }
      }
      else {
        copy[prefix + p] = obj[p];
      }
    }
  }
  return copy;
}

var myObj = {
  a: "level 1",
  b: {
    a: "level 2",
    b: {
      a: "level 3",
      b: "level 3"
    }
  }
}

var flattened = flatten(myObj);

إليك سريعة coffeescript النسخة القائمة إيقاف إجابة ماثيو كروملي (لم أستخدم includePrototype كما لم يكن لدي أي حاجة لذلك):

flatten = (obj, into = {}, prefix = '', sep = '_') ->
  for own key, prop of obj
    if typeof prop is 'object' and prop not instanceof Date and prop not instanceof RegExp
      flatten prop, into, prefix + key + sep, sep
    else
      into[prefix + key] = prop
  into

وإصدار Unflatten الأساسي، والتي من شأنها أن تفشل بلا شك مع فواصل متكررة وغيرها من هذه الخدامة:

unflatten = (obj, into = {}, sep = '_') ->
  for own key, prop of obj
    subKeys = key.split sep
    sub = into
    sub = (sub[subKey] or= {}) for subKey in subKeys[...-1]
    sub[subKeys.pop()] = prop
  into

fwiw، يمكنني استخدام هذه الوظائف لدفع الرسوم البيانية كائن أحمر الخلاص, ، والتي تدعم فقط عمق واحد من أزواج المفتاح / القيمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top