জাভাস্ক্রিপ্ট স্ট্রিংটি বিন্দু সংকেতকে কোনও অবজেক্ট রেফারেন্সে রূপান্তর করুন


214

একটি জেএস অবজেক্ট দেওয়া হয়েছে

var obj = { a: { b: '1', c: '2' } }

এবং একটি স্ট্রিং

"a.b"

আমি কীভাবে স্ট্রিংটিকে ডট নোটেশনে রূপান্তর করতে পারি যাতে আমি যেতে পারি

var val = obj.a.b

যদি স্ট্রিংটি ঠিক থাকে তবে 'a'আমি ব্যবহার করতে পারি obj[a]। তবে এটি আরও জটিল। আমি ধারণা করি এখানে কিছু সরল পদ্ধতি রয়েছে তবে এটি বর্তমানে পালিয়ে যায়।


25
@ আন্দ্রে evalদুষ্ট! এটি ব্যবহার করবেন না
কেভিনজি

5
এফওয়াইআই: আমি সবেমাত্র কিছু আকর্ষণীয় গতির পরীক্ষা করেছি: jsperf.com/dereferences-object-property-path-from-string
জেমস উইলকিনস

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

সম্পর্কিত: নেস্টেড
জেএসএন

উত্তর:


437

সাম্প্রতিক দ্রষ্টব্য: আমি যখন এই উত্তরটি অনেকগুলি উত্সাহ পেয়েছি তা নিয়ে চাটুকার করার সময় আমিও কিছুটা আতঙ্কিত হয়েছি। যদি "xabc" এর মতো ডট-নোটেশন স্ট্রিংগুলিকে রেফারেন্সে রূপান্তর করতে হয় তবে এটি (সম্ভবত) একটি লক্ষণ হতে পারে যে এখানে খুব ভুল কিছু চলছে (যদি না আপনি কিছু অদ্ভুত deserialization করছেন তবে)।

এর অর্থ এই যে, যে উত্তরদাতারা এই উত্তরের পথ খুঁজে পান তাদের অবশ্যই নিজের কাছে প্রশ্ন জিজ্ঞাসা করতে হবে "আমি কেন এটি করছি?"

আপনার ব্যবহারের কেসটি যদি ছোট হয় এবং আপনি পারফরম্যান্সের সমস্যাগুলিতে না চলে যান তবে এটি করা সাধারণত আপনার পক্ষে ঠিক আছে এবং পরে এটি আরও জটিল করার জন্য আপনার বিমূর্ততাটি তৈরি করার প্রয়োজন হবে না। আসলে, যদি এটি কোডের জটিলতা হ্রাস করে এবং জিনিসগুলিকে সহজ রাখে, আপনার সম্ভবত এগিয়ে যাওয়া উচিত এবং ওপি যা চাইছে তা করা উচিত । তবে, যদি এটি না হয় তবে বিবেচনা করুন এগুলির কোনও প্রয়োগ হয় কিনা:

কেস 1 : আপনার ডেটা নিয়ে কাজ করার প্রাথমিক পদ্ধতি হিসাবে (যেমন আপনার অ্যাপ্লিকেশনটির চারপাশে অবজেক্টগুলি পাস করার এবং সেগুলি অবনমিত করার ডিফল্ট রূপ হিসাবে)। "আমি কীভাবে কোনও স্ট্রিং থেকে কোনও ফাংশন বা পরিবর্তনশীল নামটি সন্ধান করতে পারি" জিজ্ঞাসা করার মতো।

  • এটি খারাপ প্রোগ্রামিং অনুশীলন (বিশেষত অপ্রয়োজনীয় রূপান্তরকরণ এবং একধরণের লঙ্ঘন ফাংশন সাইড-এফেক্ট-মুক্ত কোডিং শৈলীতে রয়েছে এবং এতে পারফরম্যান্স হিট হবে)। এই ক্ষেত্রে নিজেকে যে নোটিশগুলি আবিষ্কার করে, তাদের পরিবর্তে অ্যারের উপস্থাপনাগুলির সাথে কাজ করা বিবেচনা করা উচিত, যেমন ['x', 'ক', 'বি', 'সি'], অথবা সম্ভব হলে আরও সরাসরি / সরল / সোজা কিছু: হারানো না যেমন প্রথমদিকে তাদের উল্লেখগুলির ট্র্যাক করুন (সবচেয়ে আদর্শ যদি এটি কেবল ক্লায়েন্ট-সাইড বা কেবল সার্ভার-সাইড) হয়, ইত্যাদি ((পূর্ব-বিদ্যমান ইউনিক আইডি যোগ করতে অকার্যকর হবে, তবে যদি অন্যথায় অনুমানের প্রয়োজন হয় তবে এটি ব্যবহার করা যেতে পারে নির্বিশেষে অস্তিত্ব।)

কেস 2 : সিরিয়ালযুক্ত ডেটা বা ব্যবহারকারীর কাছে প্রদর্শিত হবে এমন ডেটা নিয়ে কাজ করা। তারিখ অবজেক্টের চেয়ে স্ট্রিং "1999-12-30" হিসাবে ব্যবহার করার মতো (যা সতর্ক না হলে টাইমজোন বাগ বা সংযোজন সিরিয়ালের জটিলতা সৃষ্টি করতে পারে)। অথবা আপনি জানেন আপনি কি করছেন।

  • এটা সম্ভবত ঠিক আছে। সাবধান থাকুন যে কোনও বিন্দুর স্ট্রিং না রয়েছে "।" আপনার স্যানিটাইজড ইনপুট টুকরাগুলিতে।

আপনি যদি এই উত্তরটি সারাক্ষণ ব্যবহার করে এবং স্ট্রিং এবং অ্যারের মধ্যে পিছনে রূপান্তরিত করে নিজেকে খুঁজে পান তবে আপনার খারাপ অবস্থা হতে পারে এবং একটি বিকল্প বিবেচনা করা উচিত।

এখানে একটি মার্জিত ওয়ান-লাইনার যা অন্যান্য সমাধানের চেয়ে 10x ছোট:

function index(obj,i) {return obj[i]}
'a.b.etc'.split('.').reduce(index, obj)

[সম্পাদনা করুন] বা ইসমাস্ক্রিপ্ট 6 এ:

'a.b.etc'.split('.').reduce((o,i)=>o[i], obj)

(আমি মনে করি না যে অন্যদের মতো এটি সর্বদা খারাপ বলে মনে হয় এটি যেমন হয় (যদিও এটি সাধারণত হয়) তবে তবুও এই লোকেরা সন্তুষ্ট হবে যে এই পদ্ধতিটি বুদ্ধিমান ব্যবহার করে না The উপরেরটি obj.a.b.etcদেওয়া objএবং স্ট্রিংটি খুঁজে পাবে "a.b.etc"))

reduceECMA-262 স্ট্যান্ডার্ড (5 তম সংস্করণ) থাকা সত্ত্বেও যারা এখনও ব্যবহার করতে ভয় পান তাদের প্রতিক্রিয়া হিসাবে , এখানে একটি দুই-লাইন পুনরাবৃত্তিমূলক বাস্তবায়ন দেওয়া হয়েছে:

function multiIndex(obj,is) {  // obj,['1','2','3'] -> ((obj['1'])['2'])['3']
    return is.length ? multiIndex(obj[is[0]],is.slice(1)) : obj
}
function pathIndex(obj,is) {   // obj,'1.2.3' -> multiIndex(obj,['1','2','3'])
    return multiIndex(obj,is.split('.'))
}
pathIndex('a.b.etc')

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

সম্পাদনা করুন :

মন্তব্যে একটি আকর্ষণীয় প্রশ্নের উত্তর দিতে:

আপনি কিভাবে এটি একটি সেটারে পরিণত করবেন? মানগুলি কেবল পথ দিয়েই ফেরত নয়, ফাংশনে কোনও নতুন মান প্রেরণ করা হলে সেগুলি সেট করাও হবে? - সোয়াডার জুন 28:42 এ

(sideenote: দুর্ভাগ্যক্রমে কোনও সেটারের সাথে কোনও জিনিস ফেরত দিতে পারবেন না, কারণ এটি কলিং কনভেনশন লঙ্ঘন করবে; মন্তব্যকারী মনে করছেন পরিবর্তে কোনও সাধারণ সেটার-শৈলীর ফাংশনটি করার মতো পার্শ্ব-প্রতিক্রিয়া সহ উল্লেখ index(obj,"a.b.etc", value)করছেন obj.a.b.etc = value))

reduceস্টাইল সত্যিই যে উপযুক্ত নয়, কিন্তু আমরা recursive বাস্তবায়ন পরিবর্তন করতে পারেন:

function index(obj,is, value) {
    if (typeof is == 'string')
        return index(obj,is.split('.'), value);
    else if (is.length==1 && value!==undefined)
        return obj[is[0]] = value;
    else if (is.length==0)
        return obj;
    else
        return index(obj[is[0]],is.slice(1), value);
}

ডেমো:

> obj = {a:{b:{etc:5}}}

> index(obj,'a.b.etc')
5
> index(obj,['a','b','etc'])   #works with both strings and lists
5

> index(obj,'a.b.etc', 123)    #setter-mode - third argument (possibly poor form)
123

> index(obj,'a.b.etc')
123

... যদিও ব্যক্তিগতভাবে আমি পৃথক ফাংশন করার পরামর্শ দিই setIndex(...)। আমি একটি পক্ষের নোটে শেষ করতে চাই যে প্রশ্নের মূল পোজারটি (উচিত?) .splitস্ট্রিংয়ের পরিবর্তে সূচকগুলির অ্যারেগুলি (যা তারা পেতে পারে) নিয়ে কাজ করতে পারে ; যদিও কোনও সুবিধামতনের কার্যক্রমে সাধারণত কিছুই ভুল হয় না।


একজন মন্তব্যকারী জিজ্ঞাসা করলেন:

অ্যারে সম্পর্কে কি? "আব [4] .সিডি [1] [2] [3]" এর মতো কিছু? -AlexS

জাভাস্ক্রিপ্ট একটি খুব অদ্ভুত ভাষা; সাধারণ অবজেক্টগুলিতে কেবল তাদের সম্পত্তি কী হিসাবে স্ট্রিং থাকতে পারে, উদাহরণস্বরূপ যদি যদি xজেনেরিক কোনও জিনিস ছিল x={}তবে x[1]তা হয়ে উঠবে x["1"]... আপনি সেই অধিকারটি পড়েন ... হ্যাঁ ...

জাভাস্ক্রিপ্ট অ্যারেগুলি (যা তারা নিজেরাই বস্তুর উদাহরণ) আপনার পছন্দ মতো কিছু করতে পারলেও পূর্ণসংখ্যা কীগুলি বিশেষত উত্সাহ দেয় x=[]; x["puppy"]=5;

তবে সাধারণভাবে (এবং এর ব্যতিক্রম রয়েছে), x["somestring"]===x.somestring(যখন এটি অনুমোদিত; আপনি করতে পারবেন না x.123)।

(মনে রাখবেন যে আপনি জেএস সংকলকটি ব্যবহার করছেন তা বেছে নিতে পারে, সম্ভবত এটি সাইনার উপস্থাপনাগুলিতে সংকলন করতে পারে যদি এটি প্রমাণ করে যে এটি অনুমান লঙ্ঘন করবে না))

সুতরাং আপনার প্রশ্নের উত্তর নির্ভর করবে আপনি এই বিষয়গুলি কেবলমাত্র পূর্ণসংখ্যা গ্রহণ করবেন কিনা (আপনার সমস্যার ডোমেনে সীমাবদ্ধতার কারণে) বা না তা নির্ভর করে। ধরা যাক না। তারপরে একটি বৈধ এক্সপ্রেশন হ'ল বেস শনাক্তকারী প্লাস কিছু .identifierএস প্লাস কিছু ["stringindex"]এস a

এটি তখন সমান হবে a["b"][4]["c"]["d"][1][2][3], যদিও আমাদের সম্ভবত সমর্থন করা উচিত a.b["c\"validjsstringliteral"][3]। একটি বৈধ স্ট্রিং আক্ষরিক পার্স কীভাবে করতে হয় তা দেখতে আপনাকে স্ট্রিং লিটারালগুলির একমাস্ক্রিপ্ট ব্যাকরণ বিভাগটি পরীক্ষা করতে হবে। প্রযুক্তিগতভাবে আপনিও পরীক্ষা করতে চান (আমার প্রথম উত্তরের মতো নয়) এটি aএকটি বৈধ জাভাস্ক্রিপ্ট শনাক্তকারী

আপনার প্রশ্নের একটি সরল উত্তর যদিও, যদি আপনার স্ট্রিং কমা বা বন্ধনী থাকে না , শুধু সেটে না দৈর্ঘ্য 1+ অক্ষরের ক্রমের সাথে মেলাতে হতে হবে ,বা [বা ]:

> "abc[4].c.def[1][2][\"gh\"]".match(/[^\]\[.]+/g)
// ^^^ ^  ^ ^^^ ^  ^   ^^^^^
["abc", "4", "c", "def", "1", "2", ""gh""]

যদি আপনার স্ট্রিংগুলিতে পালানোর অক্ষর বা "অক্ষর না থাকে এবং আইডেন্টিফায়ারনামগুলি স্ট্রিংলাইটারালগুলির একটি সাবল্যাংগিউজ (আমার মনে হয় ???) আপনি প্রথমে আপনার বিন্দুগুলিকে [] রূপান্তর করতে পারেন:

> var R=[], demoString="abc[4].c.def[1][2][\"gh\"]";
> for(var match,matcher=/^([^\.\[]+)|\.([^\.\[]+)|\["([^"]+)"\]|\[(\d+)\]/g; 
      match=matcher.exec(demoString); ) {
  R.push(Array.from(match).slice(1).filter(x=>x!==undefined)[0]);
  // extremely bad code because js regexes are weird, don't use this
}
> R

["abc", "4", "c", "def", "1", "2", "gh"]

অবশ্যই, সর্বদা সতর্ক থাকুন এবং কখনই আপনার ডেটা বিশ্বাস করবেন না। এটি করার কিছু খারাপ উপায় যা কিছু ব্যবহারের ক্ষেত্রে কার্যকর হতে পারে তার মধ্যে রয়েছে:

// hackish/wrongish; preprocess your string into "a.b.4.c.d.1.2.3", e.g.: 
> yourstring.replace(/]/g,"").replace(/\[/g,".").split(".")
"a.b.4.c.d.1.2.3"  //use code from before

বিশেষ 2018 সম্পাদনা:

আসুন আমরা পুরো বৃত্তে চলে আসি এবং সর্বাধিক অদক্ষ, ভয়াবহ-ওভারমেটপ্রোগ্র্যামড সমাধানটি করতে পারি যা সিন্টেক্সটিকাল বিশুদ্ধতার হ্যামফিসারির স্বার্থে ... ES6 প্রক্সি অবজেক্টের সাথে! ... আসুন কিছু বৈশিষ্ট্যও সংজ্ঞায়িত করা যাক (imho সূক্ষ্ম এবং বিস্ময়কর তবে) ভুল-লিখিত গ্রন্থাগারগুলি ভেঙে দিতে পারে। আপনি যদি পারফরম্যান্স, স্যানিটি (আপনার বা অন্যদের), আপনার কাজ ইত্যাদির বিষয়ে যত্নশীল হন তবে এটি ব্যবহারের বিষয়ে আপনাকে সম্ভবত সতর্ক হওয়া উচিত

// [1,2,3][-1]==3 (or just use .slice(-1)[0])
if (![1][-1])
    Object.defineProperty(Array.prototype, -1, {get() {return this[this.length-1]}}); //credit to caub

// WARNING: THIS XTREME™ RADICAL METHOD IS VERY INEFFICIENT,
// ESPECIALLY IF INDEXING INTO MULTIPLE OBJECTS,
// because you are constantly creating wrapper objects on-the-fly and,
// even worse, going through Proxy i.e. runtime ~reflection, which prevents
// compiler optimization

// Proxy handler to override obj[*]/obj.* and obj[*]=...
var hyperIndexProxyHandler = {
    get: function(obj,key, proxy) {
        return key.split('.').reduce((o,i)=>o[i], obj);
    },
    set: function(obj,key,value, proxy) {
        var keys = key.split('.');
        var beforeLast = keys.slice(0,-1).reduce((o,i)=>o[i], obj);
        beforeLast[keys[-1]] = value;
    },
    has: function(obj,key) {
        //etc
    }
};
function hyperIndexOf(target) {
    return new Proxy(target, hyperIndexProxyHandler);
}

ডেমো:

var obj = {a:{b:{c:1, d:2}}};
console.log("obj is:", JSON.stringify(obj));

var objHyper = hyperIndexOf(obj);
console.log("(proxy override get) objHyper['a.b.c'] is:", objHyper['a.b.c']);
objHyper['a.b.c'] = 3;
console.log("(proxy override set) objHyper['a.b.c']=3, now obj is:", JSON.stringify(obj));

console.log("(behind the scenes) objHyper is:", objHyper);

if (!({}).H)
    Object.defineProperties(Object.prototype, {
        H: {
            get: function() {
                return hyperIndexOf(this); // TODO:cache as a non-enumerable property for efficiency?
            }
        }
    });

console.log("(shortcut) obj.H['a.b.c']=4");
obj.H['a.b.c'] = 4;
console.log("(shortcut) obj.H['a.b.c'] is obj['a']['b']['c'] is", obj.H['a.b.c']);

আউটপুট:

আপত্তিটি হ'ল: {"a": {"b": {"c": 1, "d": 2}}}

(প্রক্সি ওভাররাইড পান) Hজেক্ট হাইপার ['এবিসি'] হ'ল: ১

(প্রক্সি ওভাররাইড সেট) objHyper ['abc'] = 3, এখন আপত্তি হ'ল: {"a": {"বি": {"সি": 3, "ডি": 2}}}

(পর্দার আড়ালে) Hজেপ হাইপারটি হ'ল: প্রক্সি {এ: {...}}

(শর্টকাট) obj.H ['abc'] = 4

(শর্টকাট) আপত্তি.এইচ ['এবিসি'] হ'ল আপত্তি ['ক'] ['বি'] ['গ'] হ'ল: ৪

অযোগ্য ধারণা: আপনি ইনপুট আর্গুমেন্টের উপর ভিত্তি করে প্রেরণের জন্য উপরেরটি সংশোধন করতে পারেন; হয় .match(/[^\]\[.]+/g)সমর্থন করার জন্য পদ্ধতিটি ব্যবহার করুন obj['keys'].like[3]['this'], বা যদি instanceof Array, তবে কেবল কোনও অ্যারেটিকে ইনপুট হিসাবে গ্রহণ করুন keys = ['a','b','c']; obj.H[keys]


পরামর্শ হিসাবে আপনি সম্ভবত একটি 'নরম' NaN- স্টাইল পদ্ধতিতে অপরিবর্তিত সূচকগুলি পরিচালনা করতে চান (উদাহরণস্বরূপ, index({a:{b:{c:...}}}, 'a.x.c')টাইপ এয়াররের পরিবর্তে অপরিজ্ঞাত ফিরে আসা) ...:

1) এটি 1-মাত্রিক সূচক পরিস্থিতিতে ({}) ['উদাহরণস্বরূপ'] == অপরিজ্ঞাত, "আমাদের কোনও ত্রুটি ছুঁড়ে না দিয়ে অপরিবর্তিত হওয়া উচিত" ত্রুটিযুক্ত পরিবর্তনের পরিবর্তে আমাদের ত্রুটি ছুঁড়ে ফেলা উচিত of ত্রুটি "এন-মাত্রিক পরিস্থিতিতে।

2) এই আছে না দৃষ্টিকোণ যে আমরা করছেন থেকে জানার জন্য x['a']['x']['c'], যা উপরোক্ত উদাহরণে একটি TypeError সঙ্গে ব্যর্থ হবে।

এটি বলেছিল, আপনি আপনার হ্রাসকরণের ক্রিয়াটি এর সাথে প্রতিস্থাপন করে এই কাজটি করবেন:

(o,i)=>o===undefined?undefined:o[i], বা (o,i)=>(o||{})[i]

(আপনি লুপের জন্য এবং ভাঙ্গা / ফিরে আসার ক্ষেত্রে যখনই পরবর্তী সূচিটি অপরিজ্ঞাত করে রেখেছেন বা আপনি যদি এই জাতীয় ব্যর্থতা যথেষ্ট বিরল বলে আশা করেন তবে চেষ্টা করার চেষ্টা করে আপনি এটিকে আরও দক্ষ করে তুলতে পারেন))


4
reduceবর্তমানে ব্যবহৃত সমস্ত ব্রাউজারগুলিতে সমর্থিত নয়।
রিকার্ডো তোমাসি

14
@ রিকার্ডো: Array.reduceইসিএমএ -262 স্ট্যান্ডার্ডের একটি অংশ। আপনি যদি সত্যই পুরানো ব্রাউজারগুলিকে সমর্থন করতে চান, তবে আপনি Array.prototype.reduceকোথাও প্রদত্ত নমুনা প্রয়োগের সংজ্ঞা দিতে পারেন (উদাহরণস্বরূপ বিকাশকারী.মজিলা.আর / জাভাস্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস /… )।
নিনজাগেকো

2
হ্যাঁ তবে দুটি লাইন একটি ফাংশনে রাখাই যথেষ্ট সহজ। var setget = function( obj, path ){ function index( robj,i ) {return robj[i]}; return path.split('.').reduce( index, obj ); }
nevf

3
আমি এই মার্জিত উদাহরণটি ভালোবাসি, ধন্যবাদ নিনজেকেকো। অ্যারে স্টাইলের স্বরলিপি, পাশাপাশি খালি স্ট্রিংগুলি পরিচালনা করতে আমি এটি বাড়িয়েছি - আমার উদাহরণটি এখানে দেখুন: jsfiddle.net/sc0
ত্তি

2
@ নিনজাগেকো আপনি কীভাবে এটি একটি সেটারে পরিণত করবেন? মানগুলি কেবল পথ দিয়েই ফেরত নয়, ফাংশনে কোনও নতুন মান প্রেরণ করা হলে সেগুলি সেট করাও হবে?
সোয়াডার

64

যদি আপনি লোডাশ ব্যবহার করতে পারেন তবে একটি ফাংশন রয়েছে যা ঠিক তা করে:

_.get (অবজেক্ট, পাথ, [ডিফল্ট মূল্য])

var val = _.get(obj, "a.b");

4
দ্রষ্টব্য: _.get(object, path)কোনও পথ না পাওয়া গেলে ভাঙবে না। 'a.b.etc'.split('.').reduce((o,i)=>o[i], obj)আছে। আমার নির্দিষ্ট ক্ষেত্রে - প্রতিটি ক্ষেত্রে নয় - ঠিক আমার যা প্রয়োজন ছিল। ধন্যবাদ!
মিঃ বি।

1
@ বিএনপিতে ফিরছেন বি। লোডাসের সর্বশেষ সংস্করণটির তৃতীয়, alচ্ছিক, যুক্তি রয়েছে defaultValue_.get()পদ্ধতি আয় তাহলে ডিফল্ট মান _.get()সমাধান করা থেকে undefined, তাই এটি সেট যাই হোক না কেন আপনি চান এবং মান সেট জন্য দেখুন।
স্টেপ পাওয়ার্ড

7
ভাবছেন যে কেউ, এটি সমর্থন করে _.set(object, path, value)
জেফরি রুজেন্ডাল

19

পুনরাবৃত্তি সঙ্গে আরও কিছু জড়িত উদাহরণ।

function recompose(obj,string){
    var parts = string.split('.');
    var newObj = obj[parts[0]];
    if(parts[1]){
        parts.splice(0,1);
        var newString = parts.join('.');
        return recompose(newObj,newString);
    }
    return newObj;
}


var obj = { a: { b: '1', c: '2', d:{a:{b:'blah'}}}};

alert(recompose(obj,'a.d.a.b')); //blah

19

আপনি লড্যাশ.জেটও ব্যবহার করতে পারেন

আপনি কেবল এই প্যাকেজটি ইনস্টল করুন (এনএমপি আই - সেভ লড্যাশ.জেট) এবং তারপরে এটি ব্যবহার করুন:

const get = require('lodash.get');

const myObj = { user: { firstName: 'Stacky', lastName: 'Overflowy' }, id: 123 };

console.log(get(myObj, 'user.firstName')); // prints Stacky
console.log(get(myObj, 'id')); //prints  123

//You can also update values
get(myObj, 'user').firstName = John;

10

আপনি যদি একই পথটি বহুবার অচল করার প্রত্যাশা করেন, তবে প্রতিটি ডট নোটেশন পাথের জন্য একটি ক্রিয়াকলাপ তৈরি করার পক্ষে এখন পর্যন্ত সর্বোত্তম পারফরম্যান্স রয়েছে (উপরের মন্তব্যে জেমস উইলকিন্স লিঙ্কযুক্ত পারফ টেস্টগুলিতে প্রসারিত)।

var path = 'a.b.x';
var getter = new Function("obj", "return obj." + path + ";");
getter(obj);

সুরক্ষা এবং সবচেয়ে খারাপ ক্ষেত্রে পারফরম্যান্সের ক্ষেত্রে ফাংশন কন্সট্রাক্টর ব্যবহার করে অ্যাভাল () এর মতো কিছু ত্রুটি রয়েছে, তবে আইএমও এটি এমন ক্ষেত্রে খুব খারাপভাবে ব্যবহারযোগ্য একটি সরঞ্জাম যেখানে আপনার চরম গতিশীলতা এবং উচ্চ পারফরম্যান্সের সংমিশ্রণ প্রয়োজন। আমি অ্যারে ফিল্টার ফাংশনগুলি তৈরি করতে এবং এঙ্গুলারজেএস ডাইজেস্ট লুপের ভিতরে তাদের কল করতে এই পদ্ধতিটি ব্যবহার করি। আমার প্রোফাইলগুলি ধারাবাহিকভাবে অ্যারে.ফিল্টার দেখায় () পদক্ষেপটি 1 মিমি থেকে কম পদক্ষেপ নিতে এবং প্রায় 2000 জটিল অবজেক্টগুলিকে ফিল্টার করে, গতিশীলভাবে সংজ্ঞায়িত পাথগুলি 3-4 স্তরের গভীরতা ব্যবহার করে।

সেটার ফাংশন তৈরি করতে অবশ্যই অনুরূপ পদ্ধতি ব্যবহার করা যেতে পারে:

var setter = new Function("obj", "newval", "obj." + path + " = newval;");
setter(obj, "some new val");

1
যদি আপনাকে একই পথগুলিকে দীর্ঘ সময়ের ব্যবধানে ডিফারেন্স করতে হয় তবে উপরের jsperf.com লিঙ্কটি কীভাবে পরবর্তী সময়ে ফাংশনটি সংরক্ষণ এবং সন্ধান করতে হবে তার একটি উদাহরণ দেখায়। ফাংশন কনস্ট্রাক্টরকে কল করার কাজটি মোটামুটি ধীর, তাই সম্ভব হলে উচ্চারণের কোডটি পুনরাবৃত্তি এড়াতে ফলাফলগুলি মেমোয়েজ করা উচিত।
কেভিন ক্রামলে

9

মূল পোস্টের অনেক বছর পরে। এখন 'অবজেক্ট-পাথ' নামে একটি দুর্দান্ত গ্রন্থাগার রয়েছে। https://github.com/mariocasciaro/object-path

NPM এ উপলব্ধ এবং আবাস https://www.npmjs.com/package/object-path

এটি এতটা সহজ:

objectPath.get(obj, "a.c.1");  //returns "f"
objectPath.set(obj, "a.j.0.f", "m");

এবং গভীরভাবে নেস্টেড বৈশিষ্ট্য এবং অ্যারেগুলির জন্য কাজ করে।


7

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

const getValue = (object, keys) => keys.split('.').reduce((o, k) => (o || {})[k], object);

console.log(getValue({ a: { b: '1', c: '2' } }, 'a.b'));
console.log(getValue({ a: { b: '1', c: '2' } }, 'foo.bar.baz'));


6

মনে রাখবেন আপনি ইতিমধ্যে লোডাশ ব্যবহার করছেন তবে আপনি propertyবা getফাংশনগুলি ব্যবহার করতে পারেন :

var obj = { a: { b: '1', c: '2' } };
_.property('a.b')(obj); // => 1
_.get(obj, 'a.b'); // => 1

ইন্ডস্কোরেরও একটি propertyফাংশন রয়েছে তবে এটি ডট স্বীকৃতি সমর্থন করে না


1
দেখে মনে হচ্ছে অ্যান্ডস্কোর ডট সংকেত সমর্থন করে না উত্তর আপডেট হয়েছে।
টমলিন

5

অন্যান্য প্রস্তাবগুলি কিছুটা ক্রিপ্টিক, তাই আমি ভেবেছিলাম আমি অবদান রাখব:

Object.prop = function(obj, prop, val){
    var props = prop.split('.')
      , final = props.pop(), p 
    while(p = props.shift()){
        if (typeof obj[p] === 'undefined')
            return undefined;
        obj = obj[p]
    }
    return val ? (obj[final] = val) : obj[final]
}

var obj = { a: { b: '1', c: '2' } }

// get
console.log(Object.prop(obj, 'a.c')) // -> 2
// set
Object.prop(obj, 'a.c', function(){})
console.log(obj) // -> { a: { b: '1', c: [Function] } }

5

আপনি এনপিএম এ উপলব্ধ গ্রন্থাগারটি ব্যবহার করতে পারেন যা এই প্রক্রিয়াটিকে সহজ করে। https://www.npmjs.com/package/dot-object

 var dot = require('dot-object');

var obj = {
 some: {
   nested: {
     value: 'Hi there!'
   }
 }
};

var val = dot.pick('some.nested.value', obj);
console.log(val);

// Result: Hi there!

1
এটা আমাদের নজরে আনার জন্য ধন্যবাদ। খুব দরকারী মনে হচ্ছে।
nevf

এবং এই কারণেই প্রতিটি প্রকল্প 10000 নির্ভরতা :-) ইনজেক্ট করে।
মার্ভিন

4
var a = { b: { c: 9 } };

function value(layer, path, value) {
    var i = 0,
        path = path.split('.');

    for (; i < path.length; i++)
        if (value != null && i + 1 === path.length)
            layer[path[i]] = value;
        layer = layer[path[i]];

    return layer;
};

value(a, 'b.c'); // 9

value(a, 'b.c', 4);

value(a, 'b.c'); // 4

এটি করার সহজ সরল পদ্ধতির সাথে তুলনা করার সময় এটি অনেক কোড eval, তবে সাইমন উইলিসন বলেছেন, আপনার কখনই ইওল ব্যবহার করা উচিত নয়

এছাড়াও, জেএসফিডাল


দুর্দান্ত, এটি ট্রিট কাজ করে এবং সিডি সানচেজের চেয়ে সংক্ষিপ্ত। ধন্যবাদ।
nevf

মান (একটি, 'বিবিবিবিবি') অপরিবর্তিত ফিরবে না
ফ্রেম্বার্ট

4

আমি নিনজেকেকোর দ্বারা মার্জিত উত্তরটি প্রসারিত করেছি যাতে ফাংশনটি বিন্দুযুক্ত এবং / অথবা অ্যারে শৈলী উভয়ই রেফারেন্স পরিচালনা করে এবং যাতে খালি স্ট্রিংয়ের ফলে প্যারেন্ট অবজেক্টটি ফিরে আসে।

আপনি এখানে যান:

string_to_ref = function (object, reference) {
    function arr_deref(o, ref, i) { return !ref ? o : (o[ref.slice(0, i ? -1 : ref.length)]) }
    function dot_deref(o, ref) { return ref.split('[').reduce(arr_deref, o); }
    return !reference ? object : reference.split('.').reduce(dot_deref, object);
};

এখানে আমার কার্যকরী jsFizz উদাহরণ দেখুন: http://jsfiddle.net/sc0


সত্যিই ভাল সমাধান। এখানে কেবল একটি সমস্যা রয়েছে, এটি ধরে নেওয়া []হয় যে স্বরলিপিটি সর্বদা অ্যারেগুলিতে থাকে। অবজেক্ট কীগুলি সেভাবে উপস্থাপিত হতে পারে উদাহরণস্বরূপ এটি obj['some-problem/name'].list[1]ঠিক করতে আমাকে এই জাতীয় arr_derefফাংশনটি আপডেট করতে হয়েছিলjavascript function arr_deref(o, ref, i) { return !ref ? o : (o[(ref.slice(0, i ? -1 : ref.length)).replace(/^['"]|['"]$/g, '')]); }
সেরকান ইয়ারসেন

1
যদিও, আজকাল, আমি এটি করব না। আমি লোডাশ ব্যবহার করব: lodash.com/docs#get
Sc0

2
var find = function(root, path) {
  var segments = path.split('.'),
      cursor = root,
      target;

  for (var i = 0; i < segments.length; ++i) {
   target = cursor[segments[i]];
   if (typeof target == "undefined") return void 0;
   cursor = target;
  }

  return cursor;
};

var obj = { a: { b: '1', c: '2' } }
find(obj, "a.b"); // 1

var set = function (root, path, value) {
   var segments = path.split('.'),
       cursor = root,
       target;

   for (var i = 0; i < segments.length - 1; ++i) {
      cursor = cursor[segments[i]] || { };
   }

   cursor[segments[segments.length - 1]] = value;
};

set(obj, "a.k", function () { console.log("hello world"); });

find(obj, "a.k")(); // hello world

সমস্ত দ্রুত প্রতিক্রিয়া জন্য ধন্যবাদ। ইওল () সমাধানগুলি পছন্দ করবেন না। এটি এবং অনুরূপ পোস্টগুলি সেরা দেখাচ্ছে। তবে আমি এখনও একটি সমস্যা আছে। আমি obj.ab = নতুন মানটি সেট করার চেষ্টা করছি। সুনির্দিষ্টভাবে খ এর মান হ'ল একটি ফাংশন তাই আমার ob.ab (new_value) ব্যবহার করা দরকার। ফাংশনটি বলা হয় তবে মান সেট করা হয় না। আমি মনে করি এটি একটি সুযোগের বিষয় তবে আমি এখনও খনন করছি। আমি বুঝতে পারি এটি মূল প্রশ্নের ক্ষেত্রের বাইরে। আমার কোডটি নকআউট.জেএস ব্যবহার করছে এবং বি একটি কো.অবজারভেবল।
nevf

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

@ নিউভ তবে আমার এটি একটি ফাংশন দিয়ে করে with ; ডি
ম্যাককেলা

আমি যে আপডেটটি ব্যবহার করতে পেরেছিলাম তার জন্য ধন্যবাদ। @tylermwashburn - এবং আপনার সংক্ষিপ্ত বাস্তবায়নের জন্য ধন্যবাদ যা একটি ট্রিট কাজ করে। একটি দুর্দান্ত W / e সব আছে।
nevf

2

আপনি কোডের একক লাইন দিয়ে বিন্দু স্বরলিপি দ্বারা কোনও অবজেক্ট সদস্যের মান পেতে পারেন:

new Function('_', 'return _.' + path)(obj);

আপনার ক্ষেত্রে:

var obj = { a: { b: '1', c: '2' } }
var val = new Function('_', 'return _.a.b')(obj);

এটিকে সহজ করার জন্য আপনি এই জাতীয় একটি ফাংশন লিখতে পারেন:

function objGet(obj, path){
    return new Function('_', 'return _.' + path)(obj);
}

ব্যাখ্যা:

ফাংশন কনস্ট্রাক্টর একটি নতুন ফাংশন অবজেক্ট তৈরি করে। জাভাস্ক্রিপ্টে প্রতিটি ফাংশন আসলে একটি ফাংশন অবজেক্ট। ফাংশন কনস্ট্রাক্টরের সাথে স্পষ্টভাবে একটি ফাংশন তৈরি করার সিনট্যাক্সটি হ'ল:

new Function ([arg1[, arg2[, ...argN]],] functionBody)

যেখানে arguments(arg1 to argN)অবশ্যই একটি স্ট্রিং থাকতে হবে যা একটি বৈধ জাভা স্ক্রিপ্ট সনাক্তকারী এবং এর সাথে সম্পর্কিত sfunctionBody ফাংশন সংজ্ঞা সমন্বিত জাভাস্ক্রিপ্ট বিবৃতি সম্বলিত একটি স্ট্রিং।

আমাদের ক্ষেত্রে আমরা ডট নোটেশন সহ অবজেক্ট সদস্যকে পুনরুদ্ধার করতে স্ট্রিং ফাংশন বডিটির সুবিধা গ্রহণ করি।

আশা করি এটা সাহায্য করবে.


এটি কি করছে তা আপনি বিশদভাবে ব্যাখ্যা করতে পারেন? এবং কীভাবে আপনি 'আব' ইত্যাদি ফাংশন প্যারামিটার হিসাবে পাস করবেন?
nevf

1
আমি এটিকে একটি +1 দিয়েছি তবে জেএসলিন্ট হুঁশিয়ারি দিয়েছে যে "ফাংশন কনস্ট্রাক্টর ইওল এর একটি রূপ"
গাবে

2

জেট / এসইটি উত্তর যা দেশীয় প্রতিক্রিয়াতেও কাজ করে (আপনি Object.prototypeবর্তমানে নিযুক্ত করতে পারবেন না ):

Object.defineProperty(Object.prototype, 'getNestedProp', {
    value: function(desc) {
        var obj = this;
        var arr = desc.split(".");
        while(arr.length && (obj = obj[arr.shift()]));
        return obj;
    },
    enumerable: false
});

Object.defineProperty(Object.prototype, 'setNestedProp', {
    value: function(desc, value) {
        var obj = this;
        var arr = desc.split(".");
        var last = arr.pop();
        while(arr.length && (obj = obj[arr.shift()]));
        obj[last] = value;
    },
    enumerable: false
});

ব্যবহার:

var a = { values: [{ value: null }] };
var b = { one: { two: 'foo' } };

a.setNestedProp('values.0.value', b.getNestedProp('one.two'));
console.log(a.values[0].value); // foo

1

আমি রিকার্ডো টমাসির উত্তর থেকে নিম্নলিখিতগুলি অনুলিপি করেছি এবং প্রয়োজনীয় সাব-অবজেক্টগুলি তৈরি করতেও সংশোধন করেছি যা এখনও প্রয়োজনীয় হিসাবে বিদ্যমান নেই। এটি একটু কম দক্ষ (আরও বেশি)if গুলি এবং খালি জিনিস তৈরি করা) তবে এটি বেশ ভাল হওয়া উচিত।

এছাড়াও, এটি আমাদের Object.prop(obj, 'a.b', false)যেখানে আগে থাকতে পারিনি সেখানে করার অনুমতি দেবে । দুর্ভাগ্যক্রমে, এটি এখনও আমাদের নিযুক্ত করতে দেয় না undefined... এখনও কীভাবে এটি করা যায় তা নিশ্চিত নয়।

/**
 * Object.prop()
 *
 * Allows dot-notation access to object properties for both getting and setting.
 *
 * @param {Object} obj    The object we're getting from or setting
 * @param {string} prop   The dot-notated string defining the property location
 * @param {mixed}  val    For setting only; the value to set
 */
 Object.prop = function(obj, prop, val){
   var props = prop.split('.'),
       final = props.pop(),
       p;

   for (var i = 0; i < props.length; i++) {
     p = props[i];
     if (typeof obj[p] === 'undefined') {
       // If we're setting
       if (typeof val !== 'undefined') {
         // If we're not at the end of the props, keep adding new empty objects
         if (i != props.length)
           obj[p] = {};
       }
       else
         return undefined;
     }
     obj = obj[p]
   }
   return typeof val !== "undefined" ? (obj[final] = val) : obj[final]
 }

1

আপনি যদি ডট স্বরলিপি কী থাকা কোনও বস্তুকে সেই কীগুলির একটি বিন্যাসিত সংস্করণে রূপান্তর করতে চান তবে আপনি এটি ব্যবহার করতে পারেন।


এটি এমন কিছু রূপান্তর করবে

{
  name: 'Andy',
  brothers.0: 'Bob'
  brothers.1: 'Steve'
  brothers.2: 'Jack'
  sisters.0: 'Sally'
}

প্রতি

{
  name: 'Andy',
  brothers: ['Bob', 'Steve', 'Jack']
  sisters: ['Sally']
}

convertDotNotationToArray(objectWithDotNotation) {

    Object.entries(objectWithDotNotation).forEach(([key, val]) => {

      // Is the key of dot notation 
      if (key.includes('.')) {
        const [name, index] = key.split('.');

        // If you have not created an array version, create one 
        if (!objectWithDotNotation[name]) {
          objectWithDotNotation[name] = new Array();
        }

        // Save the value in the newly created array at the specific index 
        objectWithDotNotation[name][index] = val;
        // Delete the current dot notation key val
        delete objectWithDotNotation[key];
      }
    });

}

এটি JSON এর মতো "ভাইস .০.এক" এর সাথে মানগুলি প্রক্রিয়া করে না।
কার্তিক

অ্যারে সংগ্রহ সহ আরও জটিল জেএসএন প্রসেস করার জন্য আপনার কাছে কি কোনও পরামর্শ আছে?
কার্তিক

0

ব্যবহার না করেই আমার কোড এখানে eval। এটিও বোঝা সহজ।

function value(obj, props) {
  if (!props) return obj;
  var propsArr = props.split('.');
  var prop = propsArr.splice(0, 1);
  return value(obj[prop], propsArr.join('.'));
}

var obj = { a: { b: '1', c: '2', d:{a:{b:'blah'}}}};

console.log(value(obj, 'a.d.a.b')); //returns blah

0

হ্যাঁ, এটি 4 বছর আগে জিজ্ঞাসা করা হয়েছিল এবং হ্যাঁ, বেস প্রোটোটাইপগুলি বাড়ানো সাধারণত ভাল ধারণা নয় তবে, আপনি যদি সমস্ত এক্সটেনশনগুলি এক জায়গায় রাখেন তবে সেগুলি কার্যকর হতে পারে।
সুতরাং, এখানে এটি করার আমার উপায়।

   Object.defineProperty(Object.prototype, "getNestedProperty", {
    value     : function (propertyName) {
        var result = this;
        var arr = propertyName.split(".");

        while (arr.length && result) {
            result = result[arr.shift()];
        }

        return result;
    },
    enumerable: false
});

এখন আপনি ফাংশন বা অনুলিপি / পেস্টিং ফাংশন সহ মডিউলটি আমদানি না করে সর্বত্র নেস্টেড সম্পত্তি পেতে সক্ষম হবেন।

UPD.Example:

{a:{b:11}}.getNestedProperty('a.b'); //returns 11

ইউপিডি ২. পরবর্তী প্রকল্পটি আমার প্রকল্পে মঙ্গুজ ব্রোক করে। এছাড়াও আমি পড়লাম যে এটি jquery বিরতি হতে পারে। সুতরাং, এটি পরবর্তী উপায়ে কখনই করবেন না

 Object.prototype.getNestedProperty = function (propertyName) {
    var result = this;
    var arr = propertyName.split(".");

    while (arr.length && result) {
        result = result[arr.shift()];
    }

    return result;
};

0

এখানে আমার বাস্তবায়ন

বাস্তবায়ন ঘ

Object.prototype.access = function() {
    var ele = this[arguments[0]];
    if(arguments.length === 1) return ele;
    return ele.access.apply(ele, [].slice.call(arguments, 1));
}

বাস্তবায়ন 2 (স্লাইসের পরিবর্তে অ্যারে ব্যবহার করে)

Object.prototype.access = function() {
    var self = this;
    return [].reduce.call(arguments,function(prev,cur) {
        return prev[cur];
    }, self);
}

উদাহরণ:

var myobj = {'a':{'b':{'c':{'d':'abcd','e':[11,22,33]}}}};

myobj.access('a','b','c'); // returns: {'d':'abcd', e:[0,1,2,3]}
myobj.a.b.access('c','d'); // returns: 'abcd'
myobj.access('a','b','c','e',0); // returns: 11

এটি যেমন অ্যারেতে বস্তুগুলি পরিচালনা করতে পারে

var myobj2 = {'a': {'b':[{'c':'ab0c'},{'d':'ab1d'}]}}
myobj2.access('a','b','1','d'); // returns: 'ab1d'

0

এটি আমার বর্ধিত সমাধান প্রস্তাবিত: নিনজেকেকো

আমার জন্য সহজ স্ট্রিং নোটেশন যথেষ্ট ছিল না, তাই নীচের সংস্করণে এই জাতীয় জিনিসগুলিকে সমর্থন করে:

সূচক (আপত্তি, 'ডেটা। অ্যাকাউন্টস [0]। ঠিকানা [0] .পোস্টকোড');

/**
 * Get object by index
 * @supported
 * - arrays supported
 * - array indexes supported
 * @not-supported
 * - multiple arrays
 * @issues:
 *  index(myAccount, 'accounts[0].address[0].id') - works fine
 *  index(myAccount, 'accounts[].address[0].id') - doesnt work
 * @Example:
 * index(obj, 'data.accounts[].id') => returns array of id's
 * index(obj, 'data.accounts[0].id') => returns id of 0 element from array
 * index(obj, 'data.accounts[0].addresses.list[0].id') => error
 * @param obj
 * @param path
 * @returns {any}
 */
var index = function(obj, path, isArray?, arrIndex?){

    // is an array
    if(typeof isArray === 'undefined') isArray = false;
    // array index,
    // if null, will take all indexes
    if(typeof arrIndex === 'undefined') arrIndex = null;

    var _arrIndex = null;

    var reduceArrayTag = function(i, subArrIndex){
        return i.replace(/(\[)([\d]{0,})(\])/, (i) => {
            var tmp = i.match(/(\[)([\d]{0,})(\])/);
            isArray = true;
            if(subArrIndex){
                _arrIndex =  (tmp[2] !== '') ? tmp[2] : null;
            }else{
                arrIndex =  (tmp[2] !== '') ? tmp[2] : null;
            }
            return '';
        });
    }

    function byIndex(obj, i) {
        // if is an array
        if(isArray){
            isArray = false;
            i = reduceArrayTag(i, true);
            // if array index is null,
            // return an array of with values from every index
            if(!arrIndex){
                var arrValues = [];
                _.forEach(obj, (el) => {
                    arrValues.push(index(el, i, isArray, arrIndex));
                })
                return arrValues;
            }
            // if array index is specified
            var value = obj[arrIndex][i];
            if(isArray){
                arrIndex = _arrIndex;
            }else{
                arrIndex = null;
            }
            return value;
        }else{
            // remove [] from notation,
            // if [] has been removed, check the index of array
            i = reduceArrayTag(i, false);
            return obj[i]
        }
    }

    // reduce with byIndex method
    return path.split('.').reduce(byIndex, obj)
}

0

একটি মৃত ঘোড়াটি মারার ঝুঁকিতে ... আপনি যেখানে বেস অবজেক্টের সাথে একই কাঠামোর সাথে একইরকম কোনও অবজেক্টের প্রতি শ্রদ্ধা করছেন সেখানে রেফারেন্স করতে নেস্টেড জিনিসগুলি ট্র্যাভার করাতে আমি এটি সবচেয়ে দরকারী বলে মনে করি। সেই লক্ষ্যে, এটি নেস্টেড অবজেক্ট ট্রভারসাল ফাংশন সহ কার্যকর। মনে রাখবেন যে আমি পথ ধরে রাখতে একটি অ্যারে ব্যবহার করেছি। স্ট্রিং পাথ বা একটি অ্যারে ব্যবহার করার জন্য এটি সংশোধন করা তুচ্ছ হবে। এছাড়াও মনে রাখবেন যে আপনি অন্যান্য কিছু বাস্তবায়ন থেকে ভিন্ন হিসাবে মানটিকে "অপরিজ্ঞাত" নির্ধারণ করতে পারেন।

/*
 * Traverse each key in a nested object and call fn(curObject, key, value, baseObject, path)
 * on each. The path is an array of the keys required to get to curObject from
 * baseObject using objectPath(). If the call to fn() returns falsey, objects below
 * curObject are not traversed. Should be called as objectTaverse(baseObject, fn).
 * The third and fourth arguments are only used by recursion.
 */
function objectTraverse (o, fn, base, path) {
    path = path || [];
    base = base || o;
    Object.keys(o).forEach(function (key) {
        if (fn(o, key, o[key], base, path) && jQuery.isPlainObject(o[key])) {
            path.push(key);
            objectTraverse(o[key], fn, base, path);
            path.pop();
        }
    });
}

/*
 * Get/set a nested key in an object. Path is an array of the keys to reference each level
 * of nesting. If value is provided, the nested key is set.
 * The value of the nested key is returned.
 */
function objectPath (o, path, value) {
    var last = path.pop();

    while (path.length && o) {
        o = o[path.shift()];
    }
    if (arguments.length < 3) {
        return (o? o[last] : o);
    }
    return (o[last] = value);
}


0

আমি আমার প্রকল্পে এই কোডটি ব্যবহার করেছি

const getValue = (obj, arrPath) => (
  arrPath.reduce((x, y) => {
    if (y in x) return x[y]
    return {}
  }, obj)
)

ব্যবহার:

const obj = { id: { user: { local: 104 } } }
const path = [ 'id', 'user', 'local' ]
getValue(obj, path) // return 104

0

কয়েক বছর পরে, আমি এটি খুঁজে পেয়েছি যে সুযোগ এবং অ্যারে পরিচালনা করে। যেমনa['b']["c"].d.etc

function getScopedObj(scope, str) {
  let obj=scope, arr;

  try {
    arr = str.split(/[\[\]\.]/) // split by [,],.
      .filter(el => el)             // filter out empty one
      .map(el => el.replace(/^['"]+|['"]+$/g, '')); // remove string quotation
    arr.forEach(el => obj = obj[el])
  } catch(e) {
    obj = undefined;
  }

  return obj;
}

window.a = {b: {c: {d: {etc: 'success'}}}}

getScopedObj(window, `a.b.c.d.etc`)             // success
getScopedObj(window, `a['b']["c"].d.etc`)       // success
getScopedObj(window, `a['INVALID']["c"].d.etc`) // undefined

-1

আপনার প্রশ্নটি কী তা পরিষ্কার নয়। আপনার অবজেক্ট দেওয়া হয়েছে, obj.a.bআপনাকে "2" ঠিক তেমন দেবে। আপনি যদি বন্ধনী ব্যবহার করতে স্ট্রিংটি ব্যবহার করতে চান তবে আপনি এটি করতে পারেন:

var s = 'a.b';
s = 'obj["' + s.replace(/\./g, '"]["') + '"]';
alert(s); // displays obj["a"]["b"]

1
এটি এর জন্য কার্যকর হয় না a.b.cএবং তারা যা চায় তা সত্যিই পূরণ করে না .. তারা মান চায়, evalপথ নয়।
ম্যাককেলা

আমি এখন এটি ঠিক করেছি যাতে এটি কাজ করে a.b.cতবে আপনি ঠিকই বলেছেন, সম্ভবত তিনি সম্পত্তিটির মূল্য পেতে / সেট করতে চেয়েছিলেন obj.a.b। প্রশ্নটি আমার কাছে বিভ্রান্তিকর ছিল, যেহেতু তিনি বলেছিলেন যে তিনি "স্ট্রিং রূপান্তর করতে চান" ....
মার্ক আইরিচ

ভাল করেছ. :) এটা একটু অস্পষ্ট ছিল। আপনি যদিও রূপান্তরকরণের একটি ভাল কাজ করেছেন job
ম্যাককেলা

-1

এই ক্ষেত্রে আমার 10 সেন্ট এখানে রয়েছে, প্রদত্ত পথের ভিত্তিতে বেলো ফাংশন পাবেন / সেট হবে, .. নিশ্চিত আপনি এটি উন্নতি করতে পারবেন, অপসারণ || এবং Object.hasOwnPropertyআপনি যদি ভুলভাবে মিথ্যা মূল্যবোধের বিষয়ে চিন্তা করেন তবে এটিকে প্রতিস্থাপন করুন ,

আমি এটি a.b.cএবং ab2.c দিয়ে পরীক্ষা করেছি{a:{b:[0,1,{c:7}]}} এবং এটি উভয়ই সেটিং এবং পাওয়ার জন্য :) এর :)

cheerz

function helper(obj, path, setValue){
  const l = String(path).split('.');
  return l.reduce((o,i, idx)=>{
   if( l.length-idx===1)  { o[i] = setValue || o[i];return setValue ? obj : o[i];}
  o[i] = o[i] || {};
   return o[i];
  }, x)
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.