নেস্টেড জেএসওএন অবজেক্টগুলিকে সমতল / আন-ফ্ল্যাট করার দ্রুততম উপায়


159

আমি কিছু কোড একসাথে চ্যাপ্টা এবং আন-ফ্ল্যাট কমপ্লেক্স / নেস্টেড জেএসওএন অবজেক্টগুলিতে ফেলে দিয়েছি। এটি কাজ করে, তবে এটি কিছুটা ধীর গতির ('দীর্ঘ স্ক্রিপ্ট' সতর্কবার্তাটি ট্রিগার করে)।

সমতল নামগুলির জন্য আমি চাই ""। অ্যারেগুলির জন্য ডিলিমিটার এবং [INDEX] হিসাবে।

উদাহরণ:

un-flattened | flattened
---------------------------
{foo:{bar:false}} => {"foo.bar":false}
{a:[{b:["c","d"]}]} => {"a[0].b[0]":"c","a[0].b[1]":"d"}
[1,[2,[3,4],5],6] => {"[0]":1,"[1].[0]":2,"[1].[1].[0]":3,"[1].[1].[1]":4,"[1].[2]":5,"[2]":6}

আমি এমন একটি মানদণ্ড তৈরি করেছি যা আমার ব্যবহারের ক্ষেত্রে সিমুলেট করে http://jsfiddle.net/WSzec/

  • নেস্টেড জেএসওএন অবজেক্ট পান
  • চ্যাপ্টা করুন
  • এটিকে দেখুন এবং সমতল করার সময় সম্ভবত এটি সংশোধন করুন
  • এটিকে ফেরত পাঠানোর জন্য এটির আসল নেস্টেট ফর্ম্যাটটিতে ফিফলেট করুন

আমি দ্রুত কোড চাই: স্পষ্টকরণের জন্য, কোড যেটি জেএসফিডেল বেঞ্চমার্ক ( http://jsfiddle.net/WSzec/ ) উল্লেখযোগ্যভাবে দ্রুত সম্পন্ন করবে (আইআর 9+, এফএফ 24+, এবং ক্রোম 29) + +।

এখানে প্রাসঙ্গিক জাভাস্ক্রিপ্ট কোড: বর্তমান দ্রুততম: http://jsfiddle.net/WSzec/6/

JSON.unflatten = function(data) {
    "use strict";
    if (Object(data) !== data || Array.isArray(data))
        return data;
    var result = {}, cur, prop, idx, last, temp;
    for(var p in data) {
        cur = result, prop = "", last = 0;
        do {
            idx = p.indexOf(".", last);
            temp = p.substring(last, idx !== -1 ? idx : undefined);
            cur = cur[prop] || (cur[prop] = (!isNaN(parseInt(temp)) ? [] : {}));
            prop = temp;
            last = idx + 1;
        } while(idx >= 0);
        cur[prop] = data[p];
    }
    return result[""];
}
JSON.flatten = function(data) {
    var result = {};
    function recurse (cur, prop) {
        if (Object(cur) !== cur) {
            result[prop] = cur;
        } else if (Array.isArray(cur)) {
             for(var i=0, l=cur.length; i<l; i++)
                 recurse(cur[i], prop ? prop+"."+i : ""+i);
            if (l == 0)
                result[prop] = [];
        } else {
            var isEmpty = true;
            for (var p in cur) {
                isEmpty = false;
                recurse(cur[p], prop ? prop+"."+p : p);
            }
            if (isEmpty)
                result[prop] = {};
        }
    }
    recurse(data, "");
    return result;
}

সম্পাদনা 1 উপরের রূপে @ বার্গির প্রয়োগে পরিবর্তন হয়েছে যা বর্তমানে দ্রুততম। অন্যদিকে, "regex.exec" এর পরিবর্তে ".indexOf" ব্যবহার করা এফএফ-তে প্রায় 20% দ্রুত তবে ক্রোমে 20% ধীর গতিতে থাকে; সুতরাং আমি রেজিক্সটি সহজ থাকায় এটি আটকে রাখব (রেজেক্সটি প্রতিস্থাপন করার জন্য সূচিপত্র ব্যবহার করার জন্য এখানে আমার চেষ্টা http://jsfiddle.net/WSzec/2/ )।

বার্গির ধারণার উপর সম্পাদনা 2 বিল্ডিং আমি একটি দ্রুত নন-রেজেক্স সংস্করণ (এফএফ এ 3x দ্রুত এবং ক্রোমে 10% দ্রুত) তৈরি করতে পরিচালিত হয়েছি। http://jsfiddle.net/WSzec/6/ এ (বর্তমান) প্রয়োগে মূল নামের নিয়মগুলি সহজভাবে হয়, কীগুলি কোনও পূর্ণসংখ্যার সাথে শুরু করতে পারে না বা একটি সময়কাল থাকতে পারে।

উদাহরণ:

  • f "foo": bar "বার": [0]}} => {"foo.bar.0": 0

সম্পাদনা করুন 3 অ্যাডিটএমশাহর ইনলাইন পাথ পার্সিং পদ্ধতির (স্ট্রিং.স্প্লিটের চেয়ে) যুক্ত করা ফলস কর্ম সম্পাদন করতে সহায়তা করেছে। সামগ্রিক পারফরম্যান্সের উন্নতি পৌঁছে দিয়ে আমি খুব খুশি।

সর্বশেষতম jsfiddle এবং jsperf:

http://jsfiddle.net/WSzec/14/

http://jsperf.com/flatten-un-flatten/4


7
"JSON অবজেক্ট" বলে কোনও জিনিস নেই । প্রশ্নটি জেএস অবজেক্ট সম্পর্কে বলে মনে হচ্ছে।
ফেলিক্স ক্লিং

1
: এই প্রশ্নের কোড পর্যালোচনা StackExchange সাইটের জন্য আরও উপযুক্ত মনে করা হয় codereview.stackexchange.com
Aadit এম শাহ

6
@ ফেলিক্সক্লিং - জেএসএন অবজেক্ট দ্বারা আমার বোঝানো হয়েছে জেএস বস্তুগুলিতে কেবল আদিম জাভাস্ক্রিপ্ট প্রকার রয়েছে contain উদাহরণস্বরূপ, আপনি একটি জেএস অবজেক্টে কোনও ফাংশন রাখতে পারেন, তবে এটি জেএসএন-তে সিরিয়ালায়িত করা হবে না - যেমন JSON.stringify ({fn: ফাংশন () {সতর্কতা ('a');}}); -
লুই রিচি

2
[1].[1].[0]আমার কাছে ভুল দেখাচ্ছে আপনি কি নিশ্চিত যে এটি পছন্দসই ফলাফল?
বার্গি

2
দুর্ভাগ্যক্রমে একটি ত্রুটি রয়েছে: তারিখের অবজেক্টগুলি একটি খালি JSON এ রূপান্তরিত হয়।
গিয়াস্কো

উত্তর:


217

এখানে আমার সংক্ষিপ্ত বাস্তবায়ন:

Object.unflatten = function(data) {
    "use strict";
    if (Object(data) !== data || Array.isArray(data))
        return data;
    var regex = /\.?([^.\[\]]+)|\[(\d+)\]/g,
        resultholder = {};
    for (var p in data) {
        var cur = resultholder,
            prop = "",
            m;
        while (m = regex.exec(p)) {
            cur = cur[prop] || (cur[prop] = (m[2] ? [] : {}));
            prop = m[2] || m[1];
        }
        cur[prop] = data[p];
    }
    return resultholder[""] || resultholder;
};

flattenখুব বেশি পরিবর্তন হয়নি (এবং আমি নিশ্চিত না যে আপনার সত্যিই এই isEmptyকেসগুলি দরকার কিনা ):

Object.flatten = function(data) {
    var result = {};
    function recurse (cur, prop) {
        if (Object(cur) !== cur) {
            result[prop] = cur;
        } else if (Array.isArray(cur)) {
             for(var i=0, l=cur.length; i<l; i++)
                 recurse(cur[i], prop + "[" + i + "]");
            if (l == 0)
                result[prop] = [];
        } else {
            var isEmpty = true;
            for (var p in cur) {
                isEmpty = false;
                recurse(cur[p], prop ? prop+"."+p : p);
            }
            if (isEmpty && prop)
                result[prop] = {};
        }
    }
    recurse(data, "");
    return result;
}

একসাথে, তারা আপনার মানদণ্ডটি প্রায় অর্ধেক সময় চালায় (অপেরা 12.16: 00 1900ms এর পরিবর্তে ms 900ms, Chrome 1600ms এর পরিবর্তে ক্রোম 29: ~ 800ms)।

দ্রষ্টব্য: এখানে এবং উত্তর দেওয়া বেশিরভাগ সলিউশনগুলি গতিতে ফোকাস করে এবং প্রোটোটাইপ দূষণের পক্ষে সংবেদনশীল এবং অবিশ্বস্ত বস্তুগুলিতে ব্যবহার করা যায় না।


1
এটা অসাধারণ! রেজেক্স অসাধারণভাবে ভালভাবে চালিত হয় (বিশেষত ক্রোমে), আমি এটিকে সূচিপত্র যুক্তি দিয়ে প্রতিস্থাপন করার চেষ্টা করেছি, তবে কেবল এফএফ-তে একটি গতি-আপ উপলব্ধি করতে সক্ষম হয়েছি। আমি আরও একটি চতুর উন্নতি জাগানো যেতে পারে কিনা তা দেখার জন্য আমি এই প্রশ্নে একটি অনুগ্রহ যুক্ত করব, তবে এখন পর্যন্ত এটি আমার প্রত্যাশার চেয়ে বেশি।
লুই রিচি

1
আমি স্ট্রিং.স্প্লিট () দিয়ে regex.exec () প্রতিস্থাপন এবং মূল বিন্যাসটি সরল করে আপনার প্রয়োগের আরও গতি পিষে পরিচালিত করেছি। আমি আপনাকে pts প্রদানের কয়েক দিন আগে এটি দেব, তবে আমি মনে করি যে 'অর্থবহ অপ্টিমাইজেশনের প্রাচীর' পৌঁছেছে।
লুই রিচি

JSON.flatten ({}); // {'': {}} - আপনি var ফলাফলের পরে একটি লাইন যোগ করতে পারেন = {}; - যদি (ফলাফল === ডেটা) তথ্য ফেরত;
ইভান

@ ইভান: আহ, এই প্রান্তের জন্য ধন্যবাদ, যদিও শব্দার্থগতভাবে এটি খালি জিনিসগুলির জন্য অতিরিক্ত প্রতিনিধিত্বের প্রয়োজন হবে। তবে না, result === dataকাজ করবে না, তারা কখনই অভিন্ন নয়।
বার্গি

@ বার্গি হ্যাঁ আপনি ঠিক বলেছেন। অবজেক্ট.কিজ (ডেটা)। দৈর্ঘ্য === 0 যদিও কাজ করে
ইভান

26

আমি দুটি ফাংশন লিখেছি flattenএবং unflattenএকটি JSON অবজেক্ট।


একটি JSON অবজেক্ট সমতল করুন :

var flatten = (function (isArray, wrapped) {
    return function (table) {
        return reduce("", {}, table);
    };

    function reduce(path, accumulator, table) {
        if (isArray(table)) {
            var length = table.length;

            if (length) {
                var index = 0;

                while (index < length) {
                    var property = path + "[" + index + "]", item = table[index++];
                    if (wrapped(item) !== item) accumulator[property] = item;
                    else reduce(property, accumulator, item);
                }
            } else accumulator[path] = table;
        } else {
            var empty = true;

            if (path) {
                for (var property in table) {
                    var item = table[property], property = path + "." + property, empty = false;
                    if (wrapped(item) !== item) accumulator[property] = item;
                    else reduce(property, accumulator, item);
                }
            } else {
                for (var property in table) {
                    var item = table[property], empty = false;
                    if (wrapped(item) !== item) accumulator[property] = item;
                    else reduce(property, accumulator, item);
                }
            }

            if (empty) accumulator[path] = table;
        }

        return accumulator;
    }
}(Array.isArray, Object));

পারফরম্যান্স :

  1. এটি অপেরার বর্তমান সমাধানের চেয়ে দ্রুত। বর্তমান সমাধান অপেরাতে 26% ধীর।
  2. এটি ফায়ারফক্সের বর্তমান সমাধানের চেয়ে দ্রুত। বর্তমান সমাধানটি ফায়ারফক্সে 9% ধীর।
  3. এটি ক্রোমের বর্তমান সমাধানের চেয়ে দ্রুত। বর্তমান সমাধানটি ক্রোমে 29% ধীর।

একটি JSON অবজেক্টটি সমাপ্ত করুন :

function unflatten(table) {
    var result = {};

    for (var path in table) {
        var cursor = result, length = path.length, property = "", index = 0;

        while (index < length) {
            var char = path.charAt(index);

            if (char === "[") {
                var start = index + 1,
                    end = path.indexOf("]", start),
                    cursor = cursor[property] = cursor[property] || [],
                    property = path.slice(start, end),
                    index = end + 1;
            } else {
                var cursor = cursor[property] = cursor[property] || {},
                    start = char === "." ? index + 1 : index,
                    bracket = path.indexOf("[", start),
                    dot = path.indexOf(".", start);

                if (bracket < 0 && dot < 0) var end = index = length;
                else if (bracket < 0) var end = index = dot;
                else if (dot < 0) var end = index = bracket;
                else var end = index = bracket < dot ? bracket : dot;

                var property = path.slice(start, end);
            }
        }

        cursor[property] = table[path];
    }

    return result[""];
}

পারফরম্যান্স :

  1. এটি অপেরার বর্তমান সমাধানের চেয়ে দ্রুত। বর্তমান সমাধান অপেরাতে 5% ধীর।
  2. এটি ফায়ারফক্সের বর্তমান সমাধানের চেয়ে ধীর। আমার সমাধান ফায়ারফক্সে 26% ধীর।
  3. এটি ক্রোমের বর্তমান সমাধানের চেয়ে ধীর। আমার সমাধানটি ক্রোমে 6% ধীর।

একটি JSON অবজেক্টকে সমতল করুন এবং সমতল করুন :

সামগ্রিকভাবে আমার সমাধান বর্তমান সমাধানের চেয়ে সমানভাবে বা এমনকি আরও ভাল সম্পাদন করে।

পারফরম্যান্স :

  1. এটি অপেরার বর্তমান সমাধানের চেয়ে দ্রুত। বর্তমান সমাধান অপেরাতে 21% ধীর।
  2. এটি ফায়ারফক্সের বর্তমান সমাধানের মতো দ্রুত।
  3. এটি ফায়ারফক্সের বর্তমান সমাধানের চেয়ে দ্রুত। বর্তমান সমাধানটি ক্রোমে 20% ধীর।

আউটপুট ফর্ম্যাট :

একটি সমতল বস্তু বস্তুর বৈশিষ্ট্যগুলির জন্য বিন্দু চিহ্ন এবং অ্যারে সূচকগুলির জন্য বন্ধনী চিহ্নিতকরণ ব্যবহার করে:

  1. {foo:{bar:false}} => {"foo.bar":false}
  2. {a:[{b:["c","d"]}]} => {"a[0].b[0]":"c","a[0].b[1]":"d"}
  3. [1,[2,[3,4],5],6] => {"[0]":1,"[1][0]":2,"[1][1][0]":3,"[1][1][1]":4,"[1][2]":5,"[2]":6}

আমার মতে এই বিন্যাসটি কেবল বিন্দু চিহ্নিতকরণ ব্যবহার করার চেয়ে ভাল:

  1. {foo:{bar:false}} => {"foo.bar":false}
  2. {a:[{b:["c","d"]}]} => {"a.0.b.0":"c","a.0.b.1":"d"}
  3. [1,[2,[3,4],5],6] => {"0":1,"1.0":2,"1.1.0":3,"1.1.1":4,"1.2":5,"2":6}

সুবিধা :

  1. কোনও বস্তুর সমতলকরণ বর্তমান দ্রবণের তুলনায় দ্রুত।
  2. কোনও বস্তুর সমতলকরণ এবং অপরিবর্তনীয় বর্তমান সমাধানের চেয়ে তত দ্রুত বা দ্রুত।
  3. সমতল বস্তুগুলি পঠনযোগ্যতার জন্য ডট স্বরলিপি এবং বন্ধনী চিহ্ন দুটিই ব্যবহার করে।

অসুবিধাগুলি :

  1. বেশিরভাগ (তবে সমস্ত নয়) ক্ষেত্রে বর্তমান বস্তুর তুলনায় কোনও অবজেক্টকে অপসারণ করা ধীর গতির হয়।

বর্তমান জেএসফিডাল ডেমো আউটপুট হিসাবে নিম্নলিখিত মানগুলি দিয়েছে:

Nested : 132175 : 63
Flattened : 132175 : 564
Nested : 132175 : 54
Flattened : 132175 : 508

আমার আপডেট হওয়া জেএসফিডাল ডেমো আউটপুট হিসাবে নিম্নলিখিত মানগুলি দিয়েছে:

Nested : 132175 : 59
Flattened : 132175 : 514
Nested : 132175 : 60
Flattened : 132175 : 451

এর অর্থ কী তা আমি সত্যিই নিশ্চিত নই, তাই আমি jscreen ফলাফলের সাথে লেগে থাকব। সর্বোপরি jscreen হল একটি পারফরম্যান্স বেঞ্চমার্কিং ইউটিলিটি। জেএসফিডাল নয়।


খুব ঠান্ডা. অ্যারে.আইসআরে এবং অবজেক্টটিকে আরও কাছাকাছি স্থান পেতে বেনামি ফাংশনগুলি ব্যবহার করে আমি ফ্ল্যাটনের স্টাইলটি সত্যিই পছন্দ করি। আমি মনে করি আপনি জেএসপিফারফ পরীক্ষার জন্য যে পরীক্ষাটি ব্যবহার করছেন তা খুব সহজ too আমি একটি বৃহত জটিল নেস্টেড টুকরোগুলির টুকরোটির সত্যিকারের কেসটি অনুকরণ করতে আমার jsfiddle বেঞ্চমার্কে "ফিলিওবিজে ({}, 4)" অবজেক্টটি তৈরি করেছি।
লুই রিকি

আপনার বস্তুর জন্য কোডটি আমাকে দেখান এবং আমি এটিকে মানদণ্ডে অন্তর্ভুক্ত করব।
অদিত এম শাহ

2
@ লাস্টকোডার হুমম, আপনার বর্তমান প্রয়োগটি বেশিরভাগ ব্রাউজারে (বিশেষত ফায়ারফক্স) আমার চেয়ে দ্রুত বলে মনে হচ্ছে। মজার বিষয় হল অপেরাতে আমার বাস্তবায়ন দ্রুততর এবং এটি ক্রোমেও খুব খারাপ নয়। আমি মনে করি না যে এত বড় ডেটা সেট থাকা অ্যালগরিদমের গতি নির্ধারণের জন্য একটি আদর্শ কারণ কারণ: 1) বড় ডেটা সেটগুলিতে প্রচুর পরিমাণে মেমরি, পৃষ্ঠা অদলবদল ইত্যাদির প্রয়োজন হয়; এবং এটি আপনি জেএসকে নিয়ন্ত্রণ করতে পারবেন না (যেমন আপনি ব্রাউজারের করুণায় রয়েছেন) 2) আপনি যদি সিপিইউ নিবিড় কাজ করতে চান তবে জেএস সেরা ভাষা নয়। পরিবর্তে সি ব্যবহার বিবেচনা করুন। সি
অদিত এম শাহ

1
এটি একটি ভাল পয়েন্ট এবং সিন্থেটিক বনাম রিয়েল ওয়ার্ল্ড বেঞ্চমার্কিংয়ের মধ্যে পার্থক্য এনেছে। আমি বর্তমানের অনুকূলিত জেএসের পারফরম্যান্সে খুশি, সুতরাং সি ব্যবহার করার দরকার নেই
লুই রিসি

এই বাস্তবায়নে একটি প্রোটোটাইপ দূষণ unflatten({"foo.__proto__.bar": 42})
বাগও রয়েছে

12

3 ½ বছর পরে ...

আমার নিজের প্রকল্পের জন্য আমি JSON অবজেক্টগুলিকে মোঙ্গোডিবি ডট নোটেশনে সমতল করতে চেয়েছিলাম এবং একটি সহজ সমাধান নিয়ে এসেছি:

/**
 * Recursively flattens a JSON object using dot notation.
 *
 * NOTE: input must be an object as described by JSON spec. Arbitrary
 * JS objects (e.g. {a: () => 42}) may result in unexpected output.
 * MOREOVER, it removes keys with empty objects/arrays as value (see
 * examples bellow).
 *
 * @example
 * // returns {a:1, 'b.0.c': 2, 'b.0.d.e': 3, 'b.1': 4}
 * flatten({a: 1, b: [{c: 2, d: {e: 3}}, 4]})
 * // returns {a:1, 'b.0.c': 2, 'b.0.d.e.0': true, 'b.0.d.e.1': false, 'b.0.d.e.2.f': 1}
 * flatten({a: 1, b: [{c: 2, d: {e: [true, false, {f: 1}]}}]})
 * // return {a: 1}
 * flatten({a: 1, b: [], c: {}})
 *
 * @param obj item to be flattened
 * @param {Array.string} [prefix=[]] chain of prefix joined with a dot and prepended to key
 * @param {Object} [current={}] result of flatten during the recursion
 *
 * @see https://docs.mongodb.com/manual/core/document/#dot-notation
 */
function flatten (obj, prefix, current) {
  prefix = prefix || []
  current = current || {}

  // Remember kids, null is also an object!
  if (typeof (obj) === 'object' && obj !== null) {
    Object.keys(obj).forEach(key => {
      this.flatten(obj[key], prefix.concat(key), current)
    })
  } else {
    current[prefix.join('.')] = obj
  }

  return current
}

বৈশিষ্ট্য এবং / বা সতর্কতা

  • এটি কেবল JSON অবজেক্ট গ্রহণ করে। সুতরাং আপনি যদি কিছু পাস করেন তবে আপনি যা {a: () => {}}চেয়েছিলেন তা হয়তো পেতে পারেন না!
  • এটি খালি অ্যারে এবং অবজেক্টগুলি সরিয়ে দেয়। সুতরাং {a: {}, b: []}এটি সমতল হয় {}

1
ভাল লাগছে, তবে আমি পালানো উক্তিগুলির যত্ন নিচ্ছি না। তাই {"x": "abc\"{x}\"yz"}হয়ে যায় { "x": "abc"{,"x",}"yz"}যা অবৈধ।
সিমস্টেভ 7

@ সিমস্টেভ 7 আপনি ঠিক বলেছেন! এমন কিছু যা আমি সবসময় ভুলে যাই!
ইয়ান ফটো

11

ES6 সংস্করণ:

const flatten = (obj, path = '') => {        
    if (!(obj instanceof Object)) return {[path.replace(/\.$/g, '')]:obj};

    return Object.keys(obj).reduce((output, key) => {
        return obj instanceof Array ? 
             {...output, ...flatten(obj[key], path +  '[' + key + '].')}:
             {...output, ...flatten(obj[key], path + key + '.')};
    }, {});
}

উদাহরণ:

console.log(flatten({a:[{b:["c","d"]}]}));
console.log(flatten([1,[2,[3,4],5],6]));

1
আমি মনে করি JSON.stringify (সমতল ({"প্রোপ 1": 0, "প্রোপ 2": prop "প্রোপ 3": সত্য, "প্রোপ 4": "পরীক্ষার মধ্যে সম্পত্তি নামের মধ্যে বিভাজক না থাকলে আপনার আনফ্লেটিং করতে কিছুটা অসুবিধা হবে) "}})); ==> prop "prop1": 0, "prop2prop3": সত্য, "prop2prop4": "পরীক্ষা" but তবে এটি একটি সহজ ফিক্স, ES6 সিনট্যাক্সের ব্রেভিটি সত্যিই দুর্দান্ত
লুই রিচি

এটি খুব সত্য, পৃথককারীরা যুক্ত করেছে
গাই

এটি সুন্দরভাবে খেলছে না Date, কোনও ধারণা কীভাবে এটি করা যায়? উদাহরণস্বরূপ, এর সাথেflatten({a: {b: new Date()}});
এহতেশ চৌধুরী

আপনি টাইমস্ট্যাম্প ব্যবহার করতে পারে: {খ: নতুন তারিখ () getTime ()।}} এবং পরে তারিখ ফিরে আসতে নতুন তারিখ (টাইমস্ট্যাম্প) সঙ্গে
গায়

6

উপরের উত্তরের চেয়ে ধীরে ধীরে (প্রায় 1000 মিমি) চলার মতো আরও একটি পদ্ধতি এখানে রয়েছে তবে একটি আকর্ষণীয় ধারণা রয়েছে :-)

প্রতিটি সম্পত্তি চেইনের মাধ্যমে পুনরাবৃত্তি করার পরিবর্তে, এটি কেবল সর্বশেষ সম্পত্তিটি বেছে নেয় এবং মধ্যবর্তী ফলাফলগুলি সংরক্ষণ করার জন্য বাকীগুলির জন্য একটি চেহারা-সারণী ব্যবহার করে। এই লুক-আপ-টেবিলটি পুনরাবৃত্তি করা হবে যতক্ষণ না কোনও সম্পত্তি চেইন না থাকে এবং সমস্ত মান অরক্ষিত সম্পত্তিগুলিতে থাকে।

JSON.unflatten = function(data) {
    "use strict";
    if (Object(data) !== data || Array.isArray(data))
        return data;
    var regex = /\.?([^.\[\]]+)$|\[(\d+)\]$/,
        props = Object.keys(data),
        result, p;
    while(p = props.shift()) {
        var m = regex.exec(p),
            target;
        if (m.index) {
            var rest = p.slice(0, m.index);
            if (!(rest in data)) {
                data[rest] = m[2] ? [] : {};
                props.push(rest);
            }
            target = data[rest];
        } else {
            target = result || (result = (m[2] ? [] : {}));
        }
        target[m[2] || m[1]] = data[p];
    }
    return result;
};

এটি বর্তমানে dataটেবিলের জন্য ইনপুট প্যারামিটার ব্যবহার করে এবং এতে প্রচুর বৈশিষ্ট্য রাখে - একটি অ-ধ্বংসাত্মক সংস্করণও সম্ভব হওয়া উচিত। হতে পারে একটি চালাক lastIndexOfব্যবহার রেজেেক্সের (রিজেক্স ইঞ্জিনের উপর নির্ভরশীল) এর চেয়ে ভাল সম্পাদন করে।

এটি এখানে কর্মে দেখুন


আমি আপনার জবাব হ্রাস করা হয়নি। তবে আমি উল্লেখ করতে চাই যে আপনার ফাংশনটি unflattenসমতল বস্তুটি সঠিকভাবে করে না । উদাহরণস্বরূপ অ্যারে বিবেচনা করুন [1,[2,[3,4],5],6]। আপনার flattenফাংশন এই অবজেক্টে ফ্ল্যাট করে {"[0]":1,"[1][0]":2,"[1][1][0]":3,"[1][1][1]":4,"[1][2]":5,"[2]":6}। আপনার unflattenফাংশনটি ভুলভাবে চ্যাপ্টা বস্তুটিকে ফ্ল্যাট করে [1,[null,[3,4]],6]। এর কারণটি হ'ল কারণ যে বিবৃতিটি এটির আগে যুক্ত হওয়ার আগে delete data[p]অন্তর্বর্তী মানটি মুছে ফেলা হয় । এটি সমাধান করার জন্য একটি স্ট্যাক ব্যবহার করুন। :-)[2,null,5][3,4]
অদিত এম শাহ

1
আহ, আমি দেখছি, অপরিশোধিত গণনার অর্ডার ... সম্পত্তিগুলির সারি দিয়ে এটি ঠিক করতে চলেছে, দয়া করে আপনার স্ট্যাক সমাধানটি একটি নিজের উত্তরে রেখে দিন। ইঙ্গিতটির জন্য ধন্যবাদ!
বার্গি

4

আপনি https://github.com/hughsk/flat ব্যবহার করতে পারেন

নেস্টেড জাভাস্ক্রিপ্ট অবজেক্টটি নিন এবং এটিকে সমতল করুন বা সীমানাযুক্ত কী দিয়ে কোনও জিনিসকে সমাপ্ত করুন।

দস্তাবেজ থেকে উদাহরণ

var flatten = require('flat')

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
})

// {
//   'key1.keyA': 'valueI',
//   'key2.keyB': 'valueII',
//   'key3.a.b.c': 2
// }


var unflatten = require('flat').unflatten

unflatten({
    'three.levels.deep': 42,
    'three.levels': {
        nested: true
    }
})

// {
//     three: {
//         levels: {
//             deep: 42,
//             nested: true
//         }
//     }
// }

1
আপনি AngularJS এ কীভাবে ব্যবহার করবেন?
kensplanet

2

এই কোডটি পুনরাবৃত্তভাবে JSON অবজেক্টকে সমতল করে।

আমি কোডটিতে আমার সময় প্রক্রিয়াটি অন্তর্ভুক্ত করেছি এবং এটি আমাকে 1 মিমি দেয় তবে আমি নিশ্চিত নই যে এটিই সবচেয়ে নির্ভুল।

            var new_json = [{
              "name": "fatima",
              "age": 25,
              "neighbour": {
                "name": "taqi",
                "location": "end of the street",
                "property": {
                  "built in": 1990,
                  "owned": false,
                  "years on market": [1990, 1998, 2002, 2013],
                  "year short listed": [], //means never
                }
              },
              "town": "Mountain View",
              "state": "CA"
            },
            {
              "name": "qianru",
              "age": 20,
              "neighbour": {
                "name": "joe",
                "location": "opposite to the park",
                "property": {
                  "built in": 2011,
                  "owned": true,
                  "years on market": [1996, 2011],
                  "year short listed": [], //means never
                }
              },
              "town": "Pittsburgh",
              "state": "PA"
            }]

            function flatten(json, flattened, str_key) {
                for (var key in json) {
                  if (json.hasOwnProperty(key)) {
                    if (json[key] instanceof Object && json[key] != "") {
                      flatten(json[key], flattened, str_key + "." + key);
                    } else {
                      flattened[str_key + "." + key] = json[key];
                    }
                  }
                }
            }

        var flattened = {};
        console.time('flatten'); 
        flatten(new_json, flattened, "");
        console.timeEnd('flatten');

        for (var key in flattened){
          console.log(key + ": " + flattened[key]);
        }

আউটপুট:

flatten: 1ms
.0.name: fatima
.0.age: 25
.0.neighbour.name: taqi
.0.neighbour.location: end of the street
.0.neighbour.property.built in: 1990
.0.neighbour.property.owned: false
.0.neighbour.property.years on market.0: 1990
.0.neighbour.property.years on market.1: 1998
.0.neighbour.property.years on market.2: 2002
.0.neighbour.property.years on market.3: 2013
.0.neighbour.property.year short listed: 
.0.town: Mountain View
.0.state: CA
.1.name: qianru
.1.age: 20
.1.neighbour.name: joe
.1.neighbour.location: opposite to the park
.1.neighbour.property.built in: 2011
.1.neighbour.property.owned: true
.1.neighbour.property.years on market.0: 1996
.1.neighbour.property.years on market.1: 2011
.1.neighbour.property.year short listed: 
.1.town: Pittsburgh
.1.state: PA

1
আমি মনে করি, এটি typeof some === 'object'তত দ্রুত হয় some instanceof Objectযেহেতু প্রথম চেকটি O1 এ সঞ্চালিত হয় তবে দ্বিতীয় অনে যেখানে এন একটি উত্তরাধিকার শৃঙ্খলার দৈর্ঘ্য হয় (অবজেক্ট সর্বদা সেখানে সর্বশেষ হবে)।
গুলিরওয়াই

1

আমি মাইনর কোড রিফ্যাক্টরিং এবং ফাংশন নেমস্পেসের বাইরে পুনরাবৃত্ত ফাংশনটি সরানোর মাধ্যমে নির্বাচিত উত্তরে +/- 10-15% দক্ষতা যুক্ত করেছি।

আমার প্রশ্নটি দেখুন: প্রতিটি কলটিতে নেমস্পিড ফাংশনগুলি পুনরায় মূল্যায়ন করা হয়? কেন এটি নীচে ফাংশনগুলি কমিয়ে দেয়।

function _flatten (target, obj, path) {
  var i, empty;
  if (obj.constructor === Object) {
    empty = true;
    for (i in obj) {
      empty = false;
      _flatten(target, obj[i], path ? path + '.' + i : i);
    }
    if (empty && path) {
      target[path] = {};
    }
  } 
  else if (obj.constructor === Array) {
    i = obj.length;
    if (i > 0) {
      while (i--) {
        _flatten(target, obj[i], path + '[' + i + ']');
      }
    } else {
      target[path] = [];
    }
  }
  else {
    target[path] = obj;
  }
}

function flatten (data) {
  var result = {};
  _flatten(result, data, null);
  return result;
}

মানদণ্ড দেখুন ।


1

এই আমার। এটি একটি বৃহত্তর অবজেক্টে গুগল অ্যাপস স্ক্রিপ্টে <2 মিমিতে চলে। এটি পৃথককারীদের জন্য বিন্দুগুলির পরিবর্তে ড্যাশগুলি ব্যবহার করে এবং এটি বিশেষভাবে জিজ্ঞাসীর প্রশ্নের মতো অ্যারেগুলি পরিচালনা করে না, তবে এটি আমার ব্যবহারের জন্য আমি চেয়েছিলাম।

function flatten (obj) {
  var newObj = {};
  for (var key in obj) {
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      var temp = flatten(obj[key])
      for (var key2 in temp) {
        newObj[key+"-"+key2] = temp[key2];
      }
    } else {
      newObj[key] = obj[key];
    }
  }
  return newObj;
}

উদাহরণ:

var test = {
  a: 1,
  b: 2,
  c: {
    c1: 3.1,
    c2: 3.2
  },
  d: 4,
  e: {
    e1: 5.1,
    e2: 5.2,
    e3: {
      e3a: 5.31,
      e3b: 5.32
    },
    e4: 5.4
  },
  f: 6
}

Logger.log("start");
Logger.log(JSON.stringify(flatten(test),null,2));
Logger.log("done");

উদাহরণ আউটপুট:

[17-02-08 13:21:05:245 CST] start
[17-02-08 13:21:05:246 CST] {
  "a": 1,
  "b": 2,
  "c-c1": 3.1,
  "c-c2": 3.2,
  "d": 4,
  "e-e1": 5.1,
  "e-e2": 5.2,
  "e-e3-e3a": 5.31,
  "e-e3-e3b": 5.32,
  "e-e4": 5.4,
  "f": 6
}
[17-02-08 13:21:05:247 CST] done

1

এই গ্রন্থাগারটি ব্যবহার করুন:

npm install flat

ব্যবহার ( https://www.npmjs.com/package/flat থেকে) ):

চেপ্টা:

    var flatten = require('flat')


    flatten({
        key1: {
            keyA: 'valueI'
        },
        key2: {
            keyB: 'valueII'
        },
        key3: { a: { b: { c: 2 } } }
    })

    // {
    //   'key1.keyA': 'valueI',
    //   'key2.keyB': 'valueII',
    //   'key3.a.b.c': 2
    // }

আন চেপ্টা:

var unflatten = require('flat').unflatten

unflatten({
    'three.levels.deep': 42,
    'three.levels': {
        nested: true
    }
})

// {
//     three: {
//         levels: {
//             deep: 42,
//             nested: true
//         }
//     }
// }

2
আপনার উত্তরটি সম্পূর্ণ করতে আপনার কীভাবে সেই লাইব্রেরিটি ব্যবহার করতে হবে তার একটি উদাহরণ যুক্ত করা উচিত।
আন্তোনিও আলমেইদা

0

আমি ফ্ল্যাটিন কেসের একটি নতুন সংস্করণ যুক্ত করতে চাই (এটি আমার প্রয়োজন) :) যা উপরের জেএসফ্ল্ডারের সাথে আমার প্রোব অনুসারে বর্তমানে নির্বাচিতটির চেয়ে সামান্য দ্রুত is তদুপরি, আমি ব্যক্তিগতভাবে এই স্নিপেটটি কিছুটা বেশি পঠনযোগ্য দেখতে পাচ্ছি যা অবশ্যই বহু-বিকাশকারী প্রকল্পগুলির জন্য গুরুত্বপূর্ণ।

function flattenObject(graph) {
    let result = {},
        item,
        key;

    function recurr(graph, path) {
        if (Array.isArray(graph)) {
            graph.forEach(function (itm, idx) {
                key = path + '[' + idx + ']';
                if (itm && typeof itm === 'object') {
                    recurr(itm, key);
                } else {
                    result[key] = itm;
                }
            });
        } else {
            Reflect.ownKeys(graph).forEach(function (p) {
                key = path + '.' + p;
                item = graph[p];
                if (item && typeof item === 'object') {
                    recurr(item, key);
                } else {
                    result[key] = item;
                }
            });
        }
    }
    recurr(graph, '');

    return result;
}

0

আমি যে কোডটির সাথে কাজ করছি তার সমতল করতে আমি এখানে কিছু কোড লিখেছি। এটি একটি নতুন শ্রেণি তৈরি করে যা প্রতিটি নেস্টেড ক্ষেত্র নেয় এবং এটিকে প্রথম স্তরে নিয়ে আসে। আপনি কীগুলির মূল স্থান নির্ধারণের কথা মনে করে এটিকে অপসারণে পরিবর্তন করতে পারেন। এটি ধরেও নিয়েছে যে কীগুলি এমনকি নেস্টেড অবজেক্টগুলিতে অনন্য। আশা করি এটা সাহায্য করবে.

class JSONFlattener {
    ojson = {}
    flattenedjson = {}

    constructor(original_json) {
        this.ojson = original_json
        this.flattenedjson = {}
        this.flatten()
    }

    flatten() {
        Object.keys(this.ojson).forEach(function(key){
            if (this.ojson[key] == null) {

            } else if (this.ojson[key].constructor == ({}).constructor) {
                this.combine(new JSONFlattener(this.ojson[key]).returnJSON())
            } else {
                this.flattenedjson[key] = this.ojson[key]
            }
        }, this)        
    }

    combine(new_json) {
        //assumes new_json is a flat array
        Object.keys(new_json).forEach(function(key){
            if (!this.flattenedjson.hasOwnProperty(key)) {
                this.flattenedjson[key] = new_json[key]
            } else {
                console.log(key+" is a duplicate key")
            }
        }, this)
    }

    returnJSON() {
        return this.flattenedjson
    }
}

console.log(new JSONFlattener(dad_dictionary).returnJSON())

উদাহরণ হিসাবে এটি রূপান্তরিত হয়

nested_json = {
    "a": {
        "b": {
            "c": {
                "d": {
                    "a": 0
                }
            }
        }
    },
    "z": {
        "b":1
    },
    "d": {
        "c": {
            "c": 2
        }
    }
}

মধ্যে

{ a: 0, b: 1, c: 2 }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.