嵌套对象中的搜索关键字和返回值

时间:2018-09-12 09:42:37

标签: javascript arrays object lodash

可以说我的对象如下所示。它混合了不同的数组和父对象,没有层次顺序。例如

"person": {
"id": 12345,
"name": "John Doe",
"emergencyContacts": [
  {
    "name": "Jane Doe",
    "phone": "888-555-1212",
    "relationship": "spouse",
    "moreDetails": {
      "id": 12345,
      "phones": {},
      "home": "800-123-4567",
      "mobile": "877-123-1234"
    }
  },
  {
    "name": "Justin Doe",
    "phone": "877-123-1212",
    "relationship": "parent",
    "mobile": "877-123-1234"
  }
],
"workContacts": [
  {
    "name": "Jane Doe",
    "phone": "888-555-1212",
    "relationship": "spouse",
    "moreworkDetails": {
      "id": 12345,
      "phones": {},
      "home": "800-123-4567",
      "mobile": "877-123-1234"
    }
  },
  {
    "name": "Justin Doe",
    "phone": "877-123-1212",
    "relationship": "parent",
    "mobile": "877-123-1234"
  }
]
}

我希望能够搜索person的整个对象并带回键mobile的值。我猜想该对象需要展平,并创建一个新数组,并用“唯一”手机号码列表创建该数组,例如

var mobile = { 
0: 888-555-1212,
1: 800-123-4567,
2: 877-123-1234,
3: 083-111-3346
}

我已经在纯js和lodash中搜索了解决方案,但是找到的每个对象都知道父对象的名称和数组的深度-假设父对象和深度可以是无限的(这将其排除在问题{{3之外}})。任何帮助将不胜感激。谢谢

5 个答案:

答案 0 :(得分:0)

您将需要一个递归函数。有关说明,请查看评论

let person = {
  "id": 12345,
  "name": "John Doe",
  "emergencyContacts": [{
      "name": "Jane Doe",
      "phone": "888-555-1212",
      "relationship": "spouse",
      "moreDetails": {
        "id": 12345,
        "phones": {},
        "home": "800-123-4567",
        "mobile": "877-123-1234"
      }
    },
    {
      "name": "Justin Doe",
      "phone": "877-123-1212",
      "relationship": "parent",
      "mobile": "877-123-1234"
    }
  ],
  "workContacts": [{
      "name": "Jane Doe",
      "phone": "888-555-1212",
      "relationship": "spouse",
      "moreworkDetails": {
        "id": 12345,
        "phones": {},
        "home": "800-123-4567",
        "mobile": "877-123-1236"
      }
    },
    {
      "name": "Justin Doe",
      "phone": "877-123-1212",
      "relationship": "parent",
      "mobile": "877-123-1235"
    }
  ]
}
let arrys = [];

//iterate the object 
function recursive(obj, key) {
  //iterate the object
  for (let keys in obj) {
    // check if the key name is same as the desired one
    if (keys === key) {
      // then push the value to an array
      arrys.push(obj[keys])

    } else {
      // if the value of a key is an array & if it is not empty
      if (Array.isArray(obj[keys]) && obj[keys].length > 0) {
        // iterate the array. in each iteration you will get the object
        // example emergencyContacts. In each iteration 
        // call the same function with new data 
        obj[keys].forEach(function(item) {
          // pass that object to the same function
          recursive(item, key)
        })

      }
      // if the value is an object then again call the same function 
      else if (typeof obj[keys] === 'object') {
        recursive(obj[keys], key)
      }
    }
  }
}

recursive(person, 'mobile');
//create object from the array
let newObj = {}
for (let m = 0; m < arrys.length; m++) {
  newObj[m] = arrys[m]

}
console.log(newObj)

答案 1 :(得分:0)

您不需要递归。您可以使用while循环来完成此操作:

function searchFor(what, where) {
  const stack = [where];
  const result = [];
  while (stack.length) {
    const item = stack.pop();
    if (Array.isArray(item)) {
      item.forEach(el => stack.push(el));
      continue;
    }
    if (item && typeof item === "object")
      Object.entries(item).forEach(([key, value]) =>
        key === what ?
          result.push(value) :
          stack.push(value)
      )
  }
  return result;
}

答案 2 :(得分:0)

我用从我自己的库中无耻地偷来的代码概括了一下:goodcore

我选择了递归方法,因为我相信尽管代码更多,但代码更容易分析。

let obj = {
    "id": 12345,
    "name": "John Doe",
    "emergencyContacts": [{
        "name": "Jane Doe",
        "phone": "888-555-1212",
        "relationship": "spouse",
        "moreDetails": {
          "id": 12345,
          "phones": {},
          "home": "800-123-4567",
          "mobile": "877-123-1234"
        }
      },
      {
        "name": "Justin Doe",
        "phone": "877-123-1212",
        "relationship": "parent",
        "mobile": "877-123-1234"
      }
    ],
    "workContacts": [{
        "name": "Jane Doe",
        "phone": "888-555-1212",
        "relationship": "spouse",
        "moreworkDetails": {
          "id": 12345,
          "phones": {},
          "home": "800-123-4567",
          "mobile": "877-123-1236"
        }
      },
      {
        "name": "Justin Doe",
        "phone": "877-123-1212",
        "relationship": "parent",
        "mobile": "877-123-1235"
      }
    ]
  };

function isObject(it) {
    return it !== null && typeof it === "object";
}
function isArray(it) {
    return Array.isArray ? Array.isArray(it) : Object.prototype.toString.call(it) === "[object Array]";
}
function forEach(target, fn) {
    if(isArray(target)) {
        target.forEach(fn);
    } else {
        Object.entries(target).forEach(([key, value]) => fn(value, key));
    }
}
function objReduce(obj, fn, acc) {
    let a = acc;
    forEach(obj, (value, key) => {
        if(isObject(value) || isArray(value)) {
            a = objReduce(value, fn, a);
        } 
        a = fn(a, value, key);
    });
    return a;
}

objReduce(obj, (acc, cur, key) => {
    if(key === "mobile") {
        acc.push(cur);
    }
    return acc;
}, []);

基本上,它的作用是创建一个对象reduce函数,该函数将遍历所有属性并在其上运行累加器函数,就像Array.prototype.reduce对数组所做的那样。由于它可以任意处理数组和对象,因此需要一些代码。

答案 3 :(得分:0)

 returnValuesForAttribute = (attr) => {
    let mobile = {};
    let index = 0;
    Object.values(person).map(first_level => {
        if (Array.isArray(first_level)) {
            first_level.map(el => {
                if (Object.keys(el).includes(attr)) {
                    mobile[index] = el[attr];
                    index++;
                }
                Object.values(el).map(second_level => {
                    if (typeof second_level === 'object' && second_level[attr]) {
                        mobile[index] = second_level[attr];
                        index++;
                    }
                })
            })
        }
    });
    return mobile;
}
returnValuesForAttribute('mobile');

输出:{0:“ 877-123-1234”,1:“ 877-123-1234”,2:“ 877-123-1234”,3:“ 877-123-1234”}

答案 4 :(得分:0)

检测深度嵌套对象中的键并返回键的值。

 function getPropFromObj(obj, prop) {
let valueToFindByKey;
if (!Array.isArray(obj) && obj !== null && typeof obj === "object") {
  if (obj.hasOwnProperty(prop)) {
        
         valueToFindByKey = obj[prop];
       console.log(valueToFindByKey);
      } else {
   


        let i;
        for (i = 0; i < Object.keys(obj).length; i++) {
      
        
            getPropFromObj(obj[Object.keys(obj)[i]], prop);
        }
      }
      
    }
    return null;
   
  }


const objToInvestigate = {
    employeeInformation: {
      employees: {
        name: "venky",
        age: 27,
        job: "Frontend Developer",
      },
    },
  };
  getPropFromObj(objToInvestigate, "name");