如何将物体的道具从一个位置转移到另一个位置?

时间:2020-06-13 15:44:03

标签: javascript

以下是具有某些深层属性的对象。

const InitialObj = {
    Store: {propsFromStore: {}},
    Market: {propsFromMarket: {}},
    GoDown: {propsFromDown: {}},
    fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
    vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
    fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
}

无论您在哪里看到“ Store”,“ Market”或“ GoDown”,都应将其替换为以下对象中的值-无论它们的深度如何。

// these values are not separate. there are part of the above initialObj.
//These values should replace Where ever you see "Store", "Market" or "GoDown", no matter how deep they are.

// The following values should be obtained from the above initialObj. & Not as a separate object.

Store: {propsFromStore: {}},
Market: {propsFromMarket: {}},
GoDown: {propsFromDown: {}},

这样最终结果将是: 预期结果


// this is what we get when the initialObj is transformed
// note that after removing all the occurences of "Store"/ "Market" / "GoDown"; these values will be removed so that final result looks like this. (with all placeholders replaced"

const finalExpectedResult = {
    fruits: {store_c: {propsFromStore: {}, otherProps...}, otherProp1: {store_e: {propsFromStore: {}, otherProps...}, otherSubProp1: {}}, otherProp2: {}},
    vegetables: {market_d: {propsFromMarket: {}, otherProps...}, otherProp1: {otherSubProp1: {godown_r: {propsFromDown: {}, otherProps...}, }}},
    fancy:{store_t: {propsFromStore: {}, otherProps...}, market_d: {propsFromMarket: {}, otherProps...}, otherProp1: {otherSubProp1: {godown_r: {propsFromDown: {}, otherProps...}, }}},
}

请注意,这应该用相应的值替换“商店”,“市场”或“ GoDown”的所有深度出现

4 个答案:

答案 0 :(得分:0)

显而易见的解决方案是简单地对所有对象属性进行递归迭代,但是对于这种简单情况,它可能不必要地复杂且耗时。假设我们要替换所有值实例,例如"Store"之类的字符串,我们可以将对象转换为字符串并对其内容执行简单的replace函数,然后将其转换为对象。

const obj = {
    Store: {propsFromStore: {}},
    Market: {propsFromMarket: {}},
    GoDown: {propsFromDown: {}},
    fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
    vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
    fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown" }}}
}


// please note the existence of ":" in front of the searched term which ensures the replaced value is actually a value not a key of the nested objects
const replaced = JSON.parse(JSON.stringify(obj)
  .replace(/:"Store"/g, ": {\"propsFromStore\": {}}")
  .replace(/:"Market"/g, ": {\"propsFromMarket\": {}}")
  .replace(/:"GoDown"/g, ": {\"propsFromDown\": {}}"))

console.log(replaced)

当然,如果对象的属性更复杂/需要使用自己的自定义序列化方法,则此解决方案将无法工作。这种情况的一个示例:

const obj = { x: [10, undefined, null] }

console.log(JSON.stringify(obj)); // logs `{"x":[10,null,null]}` effectively losing distinction between undefined and null

const replaced = JSON.stringify(obj, (k, val) => typeof val === "undefined" ? "undefined" : val );
console.log(replaced) // with custom replacer can keep information that would otherwise be lost

const rereplaced = JSON.parse(replaced, (k, val) => val === "undefined" ? undefined : val)
console.log(rereplaced) // gets it's undefined value back

答案 1 :(得分:0)

您可以创建一个函数来检查键是“ Store”,“ Market”还是“ GoDown”之一,并将其​​替换为相应的值。 如果键的值是一个对象(typeof对象),则递归调用该函数并重复。

const obj = {
   Store: {
       propsFromStore: {}
   },
   Market: {
       propsFromMarket: {}
   },
   GoDown: {
       propsFromDown: {}
   }
}
const whiteList = ["Store", "Market", "GoDown"]

const replacer = object => Object.fromEntries(Object
    .entries(object)
    .map(([key, value]) => 
        [key, value && typeof value === "object" ? replacer(value) : whiteList.includes(value) ? obj[value] : value ]
    )
)
var initialObj = {
    fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
    vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
    fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
}
const finalObj = replacer(initialObj)
console.log(finalObj) // desired output

我希望这会有所帮助。

答案 2 :(得分:0)

您可以使用第一个函数来查找哪些道具应作为参考(商店,市场,GoDown),并通过辅助功能对其他道具使用递归:

const InitialObj = {
  Store: {propsFromStore: {}},
  Market: {propsFromMarket: {}},
  GoDown: {propsFromDown: {}},
  fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
  vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
  fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
};

function hydrateObj(obj, keys) {
  const refs = keys.reduce((o, k) => ({...o, [k]: obj[k]}), {});
  return Object.entries(obj).reduce((res, [k, v]) => {
    if(!keys.includes(k)) {
      res[k] = hydrateObjAux(v, keys, refs);
    }
    return res;
  }, {});
}

function hydrateObjAux(obj, keys, refs) {
  return Object.entries(obj).reduce((res, [k, v]) => {
    if(keys.includes(v)) {
      res[k] = refs[v];
    } else {
      res[k] = hydrateObjAux(v, keys, refs);
    }
    return res;
  }, {});
}

const res = hydrateObj(InitialObj, ['Store', 'Market', 'GoDown']);
document.body.innerHTML = '<pre>' + JSON.stringify(res, 0, 4) + '</pre>';

答案 3 :(得分:0)

根据您的评论,您用大写的首字母将替换对象与InitialObj分开。

  • 将ReplacementObject与InitialObj分开
  • 基于replacementObject递归替换键字符串 注意:我不知道您使用的是哪种类型,因此我为每种类型设置了any。如果使用ts,最好定义和设置正确的类型。

const InitialObj: any = {
    Store: {propsFromStore: {}},
    Market: {propsFromMarket: {}},
    GoDown: {propsFromDown: {}},
    fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
    vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
    fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
  }
  
  const replacementDict: any ={}
  
  // take Store, Market, GoDown from InitialObj to replacementDict
  Object.keys(InitialObj).forEach(key =>{
    // Check if the first letter is capitalised or not
    if(key[0].match(/^[A-Z]$/)){
      replacementDict[key] = InitialObj[key]
      delete InitialObj[key]
    }
  })
  
  
  function converter(obj: any){
    if(typeof obj !== "object") return
  
    Object.entries(obj).forEach(([key, value]: [any, any]) => {
      if(replacementDict[value]){
        obj[key] = replacementDict[value]
      }
      if(typeof obj[key] === "object"){
        converter(obj[key])
      }
    })
  }
  
  converter(InitialObj)
  console.log(InitialObj)