मान JSON के साथ स्वैप कुंजी


106

मेरे पास इस तरह संरचित एक बहुत बड़ी JSON वस्तु है:

{A : 1, B : 2, C : 3, D : 4}

मुझे एक ऐसे फंक्शन की जरूरत है, जो मेरे ऑब्जेक्ट में कुंजियों के साथ स्वैप कर सके और मुझे नहीं पता कि यह कैसे करना है। मुझे इस तरह एक आउटपुट की आवश्यकता होगी:

{1 : A, 2 : B, 3 : C, 4 : D}

वहाँ कोई रास्ता नहीं है कि मैं यह कर सकता हूँ मैन्युअल रूप से एक नई वस्तु बनाई गई है जहां सब कुछ स्वैप किया जाता है?
धन्यवाद


1
सभी मान संख्याएँ हैं और क्या संख्याएँ दोहराती हैं? यदि मान दोहराते हैं, तो आप उन्हें स्वैप नहीं कर पाएंगे क्योंकि वे दूसरों को अधिलेखित कर देंगे, जब तक कि आप उनके मूल्य को कुछ अद्वितीय मूल्य में नहीं बदलते। एक बेहतर समाधान हो सकता है कि स्वैप की आवश्यकता का कारण क्या है?
पैट्रिक इवांस

@PatrickEvans वे सभी संख्याएँ हैं लेकिन वे दोहराई नहीं जातीं। मैं एक बुनियादी सिफर बनाने की कोशिश कर रहा हूं।
C1D

2
यह ध्यान देने योग्य है कि इस तरह का "स्वैप" ऑपरेशन [कम से कम] दो कारणों से समस्याग्रस्त है: 1) मान स्ट्रिंग्स के लिए डाले जाते हैं जब वे कुंजी बन जाते हैं तो आश्चर्यचकित न हों जब आपके पास "अप्रत्याशित वस्तु" कुंजी है। और 2) डुप्लिकेट मान (स्ट्रिंग के बाद कास्ट) ओवरराइट हो जाते हैं। #, कम से कम, एक वस्तु के बजाय एक मानचित्र का निर्माण करके हल किया जा सकता है, इस प्रकार:function swap(obj) {return new Map(Object.entries(x).map([k, v] => [v, k]))}
ब्रूफ़

जवाबों:


118
function swap(json){
  var ret = {};
  for(var key in json){
    ret[json[key]] = key;
  }
  return ret;
}

यहाँ उदाहरण FIDDLE परिणाम देखने के लिए अपने कंसोल को चालू करना न भूलें।


ES6 संस्करण:

static objectFlip(obj) {
  const ret = {};
  Object.keys(obj).forEach(key => {
    ret[obj[key]] = key;
  });
  return ret;
}

या Array.reduce () और Object.keys () का उपयोग करना

static objectFlip(obj) {
  return Object.keys(obj).reduce((ret, key) => {
    ret[obj[key]] = key;
    return ret;
  }, {});
}

या Array.reduce () और Object.entries () का उपयोग कर

static objectFlip(obj) {
  return Object.entries(obj).reduce((ret, entry) => {
    const [ key, value ] = entry;
    ret[ value ] = key;
    return ret;
  }, {});
}


39

ES6 का उपयोग करना:

const obj = { a: "aaa", b: "bbb", c: "ccc", d: "ddd" };
Object.assign({}, ...Object.entries(obj).map(([a,b]) => ({ [b]: a })))

2
अब (2019) के लिए बेहतर समाधान लगता है ! कोई पुष्टि कर सकता है, क्या यह है? प्रदर्शन अच्छा है? शब्दार्थ एकदम सही है: हम देख सकते हैं कि वास्तव में एक सरल "मानचित्र और स्वैप" समाधान है।
पीटर क्रस

1
@ पीटर-क्रूस, आप jsben.ch/gHEtn के साथ टिंकर में आपका स्वागत है अगर मैं कुछ चूक गया, लेकिन इस जवाब और जेपीओ के जवाब के बीच एक आकस्मिक तुलना से पता चलता है कि जेपीओ के फॉर-लूप आउटपरफॉर्मर ग्रेपेक के नक्शे के दृष्टिकोण से लगभग 3 से 1 (कम से कम) पर मेरी ब्राउज़र)।
माइकल ने

36

ऑब्जेक्ट की कुंजी प्राप्त करें, और फिर प्रत्येक कुंजी के माध्यम से जाने के लिए एरे के कम फ़ंक्शन का उपयोग करें और मान को कुंजी के रूप में सेट करें, और मूल्य के रूप में कुंजी।

const data = {
  A: 1,
  B: 2,
  C: 3,
  D: 4
}
const newData = Object.keys(data).reduce(function(obj, key) {
  obj[data[key]] = key;
  return obj;
}, {});
console.log(newData);


30

ES6 / ES2015 में आप के उपयोग को जोड़ सकते हैं Object.keys और कम करने के लिए नए के साथ Object.assign समारोह, एक तीर समारोह , और एक गणना संपत्ति नाम एक बिल्कुल स्पष्ट एकल कथन समाधान के लिए।

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.keys(foo)
    .reduce((obj, key) => Object.assign({}, obj, { [foo[key]]: key }), {});

यदि आप ऑब्जेक्ट स्प्रेड ऑपरेटर (यह लिखने के रूप में चरण 3) का उपयोग करके ट्रांसपाइल कर रहे हैं, जो चीजों को थोड़ा और सरल करेगा।

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.keys(foo)
    .reduce((obj, key) => ({ ...obj, [foo[key]]: key }), {});

अंत में, यदि आपके पास Object.entries उपलब्ध हैं (लेखन के रूप में चरण 4), तो आप तर्क को एक स्पर्श अधिक (IMO) साफ कर सकते हैं।

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.entries(foo)
    .reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {});

SyntaxError: /Users/markus/Entwicklung/IT1_Beleg/public/es6/vokabeltrainer.js: अनपेक्षित टोकन (53:45) 51 | if (btoa) {52 | प्रविष्टियाँ = Object.entries (प्रविष्टियाँ)> 53 | .reduce ((obj, [key, value]) => ({... obj, [value]: key}), {}); | ^
सुपरलोकस

@Superlokkus उस त्रुटि आउटपुट की मेरी सबसे अच्छी व्याख्या यह है कि आप ऑब्जेक्ट स्प्रेड सिंटैक्स ट्रांसप्लीन नहीं कर रहे हैं, और आज के रूप में, मुझे किसी भी जावास्क्रिप्ट इंजन का पता नहीं है जो इसे मूल रूप से समर्थन करते हैं।
joslarson

1
@ Grappeq का समाधान देखें, बेहतर लगता है (सबसे सरल!)।
पीटर क्रूस

16

अब हमारे पास Object.fromEntries है:

obj => Object.fromEntries(Object.entries(obj).map(a => a.reverse()))

या

obj => Object.fromEntries(Object.entries(obj).map(([k, v]) => ([v, k])))

Node.js संस्करण 12 के साथ-साथ ऑब्जेक्ट स्वैप करने का मानक तरीका होना चाहिए।
क्षतिग्रस्त

4

@Joslarson और @jPO के पूरक के रूप में:
ES6 की आवश्यकता के बिना, आप उपयोग कर सकते हैं और कोमा ऑपरेटर :Object.keys Array.reduce

Object.keys(foo).reduce((obj, key) => (obj[foo[key]] = key, obj), {});

कुछ इसे बदसूरत लग सकते हैं, लेकिन यह "थोड़े" तेज है क्योंकि यह प्रत्येक लूप के reduceसभी गुणों को नहीं फैलाता है obj


फिर भी ... जेपीओ का जवाब लगभग 2: 1 के हिसाब से एक है। jsben.ch/R75aI (मुझे पता है कि आपकी टिप्पणी बहुत पहले से थी, लेकिन मैं ग्रेपेक के जवाब पर टिप्पणी कर रहा था और लगा कि मैं आपका उदाहरण भी दूंगा)।
माइकल ने

पूरी तरह से, पाश के लिए एक तेजी से तो बनी हुई है forEach, mapया reduceतरीकों। मैंने इस प्रतिक्रिया को es6 की आवश्यकता के बिना एक-लाइनर समाधान के लिए बनाया है और अभी भी गति / प्रभावशीलता के संदर्भ में प्रासंगिक है।
Vaidd4

जून 2019 है और यह अब नवीनतम Google Chrome में सही नहीं है, अंतर अब अस्तित्वहीन (9:10) के पास है
इवान कास्टेलानोस

यह ES6 वेरिएंट का सबसे अधिक प्रदर्शन करता है: jsben.ch/HvICq
ब्रायन एम। हंट


2

सबसे छोटा मैं ES6 का उपयोग करके आया था ..

const original = {
 first: 1,
 second: 2,
 third: 3,
 fourth: 4,
};


const modified = Object
  .entries(original)
  .reduce((all, [key, value]) => ({ ...all, [value]: key }), {});

console.log('modified result:', modified);


1

रामदा का उपयोग करना :

const swapKeysWithValues = 
  R.pipe(
    R.keys,
    R.reduce((obj, k) => R.assoc(source[k], k, obj), {})
  );

const result = swapKeysWithValues(source);

1

मेरा मानना ​​है कि npm मॉड्यूल का उपयोग करके इस कार्य को करना बेहतर है, जैसे invert-kv

invert-kv : किसी वस्तु की कुंजी / मान को उल्टा करना। उदाहरण: {फू: 'बार'} → {बार: 'फू'}

https://www.npmjs.com/package/invert-kv

const invertKv = require('invert-kv');

invertKv({foo: 'bar', unicorn: 'rainbow'});
//=> {bar: 'foo', rainbow: 'unicorn'}

1
क्यों @ Sc0ttyD से पता चलता है, या लूप के लिए एक सरल की तरह एक लाइन समाधान से बेहतर अभी तक एक और पुस्तकालय का उपयोग कर रहा है?
Arel

1

शुद्ध और बिंदु-रहित शैली में शुद्ध रामदा के साथ:

const swapKeysAndValues = R.pipe(
   R.toPairs,
   R.map(R.reverse),
   R.fromPairs,
);

या, थोड़ा और अधिक जटिल ईएस 6 संस्करण के साथ, फिर भी शुद्ध कार्यात्मक:

const swapKeysAndValues2 = obj => Object
    .entries(obj)
    .reduce((newObj, [key, value]) => ({...newObj, [value]: key}), {})

0
    var data = {A : 1, B : 2, C : 3, D : 4}
    var newData = {};
    Object.keys(data).forEach(function(key){newData[data[key]]=key});
    console.log(newData);

3
यह कहां objectसे आता है?
मैक्सिम लूनोइस

और यह वह नहीं है जो mapकरने वाला है, आप इसे यहाँ उपयोग कर रहे हैं जैसेforEach
barbsan

मैंने कभी फॉरच का इस्तेमाल नहीं किया। मैं अंडरस्कोर का उपयोग करता हूं। जेएस के प्रत्येक फंक्शन के बारे में पता नहीं था। साभार @barbsan
अनूप अग्रवाल

0

यहाँ flipping keysऔर valuesES6 में एक शुद्ध कार्यात्मक कार्यान्वयन है :

टाइपप्रति

  const flipKeyValues = (originalObj: {[key: string]: string}): {[key: string]: string} => {
    if(typeof originalObj === "object" && originalObj !== null ) {
      return Object
      .entries(originalObj)
      .reduce((
        acc: {[key: string]: string}, 
        [key, value]: [string, string],
      ) => {
        acc[value] = key
        return acc;
      }, {})
    } else {
      return {};
    }
  }

जावास्क्रिप्ट

const flipKeyValues = (originalObj) => {
    if(typeof originalObj === "object" && originalObj !== null ) {
        return Object
        .entries(originalObj)
        .reduce((acc, [key, value]) => {
          acc[value] = key
          return acc;
        }, {})
    } else {
        return {};
    }
}

const obj = {foo: 'bar'}
console.log("ORIGINAL: ", obj)
console.log("FLIPPED: ", flipKeyValues(obj))


0
function swapKV(obj) {
  const entrySet = Object.entries(obj);
  const reversed = entrySet.map(([k, v])=>[v, k]);
  const result = Object.fromEntries(reversed);
  return result;
}

यह आपकी वस्तु,, {A : 1, B : 2, C : 3, D : 4}सरणी-जैसा बना सकता है, इसलिए आपके पास हो सकता है

const o = {A : 1, B : 2, C : 3, D : 4}
const arrayLike = swapKV(o);
arrayLike.length = 5;
const array = Array.from(arrayLike);
array.shift(); // undefined
array; // ["A", "B", "C", "D"]

0

यहां एक ऐसा विकल्प है जो मानों के साथ कुंजियों को स्वैप करेगा लेकिन डुप्लिकेट नहीं खोएगा, अगर आपकी वस्तु है: {a: 1, b: 2, c: 2}, तो यह आउटपुट में एक सरणी लौटाएगा:

function swapMap(map) {
    const invertedMap = {};
    for (const key in map) {
        const value = map[key];
        invertedMap[value] = invertedMap[value] || [];
        invertedMap[value].push(key);
    }
    return invertedMap;
}
swapMap({a: "1", b: "2", c: "2"})
// Returns => {"1": ["a"], "2":["b", "c"]}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.