2011-01-06 16 views
5

में डुप्लिकेट को कम मैं की तरह एक वस्तु मिल गया है:का javascript ऑब्जेक्ट

{ 
    a : 'foo', 
    b : 'bar', 
    c : 'foo', 
    d : 'baz', 
    e : 'bar' 
} 

मैं जैसे डुप्लिकेट को कम करना चाहते:

{ 
    ac : 'foo', 
    be : 'bar', 
    d : 'baz' 
} 

ऐसा करने के लिए एक अच्छा तरीका क्या है?

कुछ चेतावनियां:

  • वहाँ केवल कभी जोड़े की एक छोटी संख्या हो जाएगा। (वर्तमान में 7 हैं; मैं कल्पना कर सकता हूं कि यह कह रहा है, 20.)
  • प्रारंभिक संपत्ति नाम केवल एक ही चरित्र होंगे, उदाहरण के लिए
  • मूल्य संभावित रूप से कई सौ वर्णों तक चल सकते हैं ।
  • दोनों गति और कोड-लंबाई बहुत महत्वपूर्ण हैं, लेकिन पंक्तियों की छोटी संख्या को देखते हुए, कोड स्पष्टता शायद अभी भी सबसे महत्वपूर्ण है।

उत्तर

0

वस्तु के प्रत्येक संपत्ति के माध्यम से जाओ और का निर्माण एक और वस्तु है, जहां कुंजी पहले के मूल्यों हैं, और मूल्यों (पहले से) कुंजी की सूची है। फिर आप उस दूसरी वस्तु के माध्यम से वापस जाते हैं और अंतिम परिणाम बनाते हैं।

कुछ इस तरह:

function noDupes(obj) { 
    var o2 = {}; 
    for (var k in obj) { 
    if (obj.hasOwnProperty(k)) { 
     var list = o2[obj[k]] || []; 
     list.push(k); 
     o2[obj[k]] = list; 
    } 
    } 
    var rv = {}; 
    for (k in o2) { 
    if (o2.hasOwnProperty(k)) 
     rv[o2[k].join('')] = k; 
    } 
    return rv; 
} 

अब, अगर मूल वस्तु के मूल्यों तार नहीं कर रहे हैं, तो चीजें और अधिक शामिल हो: केवल तार एक जावास्क्रिप्ट वस्तु में संपत्ति कुंजी हो सकता है। आप उस मामले में एक और सामान्य हैश कार्यान्वयन के लिए चारों ओर देख सकते हैं। यदि आपकी वस्तुएं बहुत छोटी हैं (10 या उससे कम गुणों से कम) तो आप एन संस्करण लिख सकते हैं, जहां आप केवल गुणों पर फिर से सक्रिय होते हैं और फिर प्रत्येक के लिए फिर से दोहराते हैं। यह शायद एक बुरा विचार होगा हालांकि यदि आपकी वस्तुएं बड़ी हो सकती हैं और आपको यह ऑपरेशन बहुत करना है।

+0

मैं सिर्फ wr था उस विचार को अपनाना। लेकिन क्या होता है यदि मानों में से एक स्ट्रिंग नहीं है? – sprugman

+0

@sprugman आह अच्छी तरह से चीजों को थोड़ा और शामिल करता है ... – Pointy

+0

हाँ, परीक्षण के बाद, यदि आपके पास ऑब्जेक्ट के रूप में कोई ऑब्जेक्ट है, तो आप परिणाम पंक्तियों जैसे {x: "[ऑब्जेक्ट ऑब्जेक्ट]"} – sprugman

1

उच्च-प्रकार की लाइब्रेरी के बिना बस प्रत्येक जोड़ी को लूप करें (hasOwnProperty का उपयोग करें) और एक हिस्टोग्राम में कुंजी जोड़ें/जोड़ें जहां हिस्टोग्राम कुंजी जोड़ी मान है और हिस्टोग्राम मान समेकित कुंजी हैं। फिर हिस्टोग्राम की कुंजी/मानों को उलट दें।

संपादित करें: यदि प्रारंभिक मान स्ट्रिंग नहीं हैं (और विपरीत रूप से मानचित्र न करें) तो मौजूदा 'पहचान हैश' लाइब्रेरी अभी भी उपरोक्त दृष्टिकोण को काम करने में सक्षम कर सकती है।

वैकल्पिक रूप से, आप कहते हैं, [[k,v],...] और सॉर्ट और उसके बाद (कल्पना यह पहले से ही हल कर रहा है) उत्पादन पास में "बराबर कुंजी" के मूल्यों विलय करने के लिए एक दृष्टिकोण एक bucket sort के लिए इसी तरह का उपयोग मैप कर सकते हैं।

यह इस तरह जा सकते हैं (कोड कीड़े हो सकता है, दृष्टिकोण ध्वनि है - यह भी इतने लंबे समय के रूप में आप मूल्यों की तुलना करने का कोई तरीका मूल्यों के रूप में मनमाने ढंग से वस्तुओं के साथ काम करेंगे):

var _f = [] 
for (var k in map) { 
    if (map.hasOwnProperty(k)) { 
    _f.push({k: k, v: map[k]}) 
    } 
} 
// you could also sort on name (a.k), if it's important 
// this makes it more versatile and deterministic in output 
// ordering than the histogram method above 
var f = _f.sort(function (a, b) { return a.v < b.v ? 1 : a.v > b.v ? -1 : 0 }) 

var res = {} 
var prev 
var name = "" 
// after the sort all {k:,v:} objects with the same values will be grouped 
// together so we only need to detect the change to the next value 
// and everything prior to that gets the merged key 
for (var i = 0; i < f.length; i++) { 
    var p = f[i] 
    if (prev != p.v && name) { 
    res[name] = prev 
    name = "" 
    } else { 
    name = name + p.k 
    } 
    prev = p.v 
} 
if (name) { // don't forget last set of values 
    res[name] = prev 
} 

// have res 
+0

मुझे लगता है कि मुझे एक कोड उदाहरण की आवश्यकता हो सकती है, जब तक कि आप पॉइंटी के समान ही नहीं मानते। – sprugman

+0

@sprugman 100% अन-परीक्षण कोड-नमूना पोस्ट किया गया ;-) –

+0

मैंने फैसला किया कि वे हमेशा स्ट्रिंग होंगे, इसलिए मैं सरल संस्करण का उपयोग कर सकता हूं, लेकिन इसके लिए धन्यवाद। बीटीडब्लू, लाइन 4 में, मुझे लगता है कि आपका मतलब है '_f.push() '। – sprugman

1
var Reduce = function(obj) 
{ 
    var temp = {}; 
    var val = ""; 

    for (var prop in obj) 
    { 
    val = obj[prop]; 
    if (temp[val]) 
     temp[val] = temp[val] + prop.toString(); 
    else 
     temp[val] = prop.toString(); 
    } 

    var temp2 = {}; 

    for (var prop in temp) 
    { 
    val = temp[prop]; 
    temp2[val] = prop.toString(); 
    } 

    return temp2; 
}; 

उपयोग के रूप में:

var obj = { 
    a :"foo", 
    b : "bar", 
    c : "foo", 
    d : "bar", 
    e : "bar" 
}; 

var ob2 = Reduce(obj); 
+0

यह अनिवार्य रूप से पॉइंटी के समान ही है। मुझे आपकी स्पष्टता के लिए तुम्हारी पसंद है, लेकिन उसके उपयोगों में ओनप्रोपर्टी है और पहले था, इसलिए मैंने उसे चेक दिया। हालांकि धन्यवाद। – sprugman

1

यह सबसे छोटा है मैं समझ सकता है:

var obj, newObj = {}; // obj is your original 
for (var i in obj) { 
    if (!obj.hasOwnProperty(i)) continue; 
    for (var j in newObj) { 
     if (newObj.hasOwnProperty(j) && newObj[j] === obj[i]) break; 
     j = ""; 
    } 
    newObj[i + j] = obj[i]; 
    j && delete newObj[j]; 
} 

स्पष्टीकरण:

  • यह मूल वस्तु, obj में प्रत्येक आइटम के माध्यम से लूप होता है, और एक नई वस्तु का उत्पादन, newObj
  • मूल में प्रत्येक आइटम के लिए, यह उसी मूल्य के लिए आधे उत्पादित newObj की खोज करता है। - परिणाम j है, या तो यदि संपत्ति मिली है तो नाम का नाम, या यदि खाली स्ट्रिंग नहीं है।
  • किसी भी मामले में, नए ऑब्जेक्ट को मूल ऑब्जेक्ट में वर्तमान प्रॉपर्टी के समान नाम की एक संपत्ति की आवश्यकता होती है, साथ ही j का यह मान भी आवश्यक है।
  • यह डुप्लीकेट बनाने के लिए, newObj में मिली संपत्ति को हटा देता है।

मान्य रूप से, लूप के भीतर j = "" सेटिंग अक्षम है। इसे आसानी से दूसरे चर सेट के साथ "" पर प्रतिस्थापित किया जा सकता है, और केवल j केवल एक मैच मिलने पर ही बदला जा सकता है। मैंने हालांकि सादगी के लिए जाने का फैसला किया।

+0

मैंने फैसला किया कि वे हमेशा तार होंगे, इसलिए मैं सरल ओ (एन) समाधान का उपयोग कर सकता हूं। हालांकि, इसके लिए धन्यवाद। – sprugman

0

अगर मैं पूरी तरह से बाहर हूं, तो मुझे माफ़ कर दो, लेकिन ऐसा लगता है कि जिस तरह से आप इन्हें जोड़ रहे हैं, आपको चाबियाँ और मूल्यों को गलत तरीके से मिला है। इस बारे में क्या?

+0

मेरे पास जो कुछ है जो मुझे शुरू करना है और मैं चाहता हूं कि मैं क्या समाप्त करना चाहता हूं। :) – sprugman

+0

स्प्रेमैन: पर्याप्त मेला। हमारे पास ज्यादा संदर्भ नहीं है, इसलिए मैंने सोचा कि मैं एक वैकल्पिक समाधान प्रदान करूंगा। –

0

प्रारंभ एक साथ कि गिनती करने के लिए एक शब्दकोश का उपयोग करता है को कम;

flippedObj = {}; 
for (var letter in obj) { 
    if (obj.hasOwnProperty(letter)) { 
     var letters = flippedObj[obj[letter]]; 
     if (letters === undefined) { 
      letters = []; 
      flippedObj[obj[letter]] = letters; 
     } 

     letters.push(letter); 
    } 
} 

(। वहाँ त्रुटियों की एक जोड़ी हो सकता है ब्रेन-संकलित):

{ 
    'foo': ['a', 'c'], 
    'bar': ['b', 'e'], 
    'baz': ['d'] 
} 

काफी आसान कन्वर्ट करने के लिए होना चाहिए एक फिसल गया तरीके में टैग। बहुत performant तरीका है, क्योंकि यह छोरों आदि के लिए कोई शब्दकोश समर्थन में बनाया का उपयोग करता है,

var flipped = Object.keys(input).reduce(function(a,b){ 
    var tag = input[b]; 
    a[tag] = (a[tag] || '') + b; 
    return a; 
}, {}); 

फ़्लिप प्रारूप के साथ एक वस्तु देता है:

// {foo: "ac", bar: "be", baz: "d"} 

तो बस प्रारूप फ्लिप:

Object.keys(flipped).reduce(function(a,b){ 
    a[flipped[b]]=b; 
    return a; 
}, {}); 

आउटपुट:

// {ac: "foo", be: "bar", d: "baz"} 
संबंधित मुद्दे