1

I am writing the following code which specified the attribute must return it even if it is of type obj, array, string or number.

I'm having some problems getting me back certain attributes going even deeper.

I would like to do this without using external modules.

Can you give me some advice?

function returnElement(obj, label) {
  let pointBool = label.includes(".");
  let arrayOpenBool = label.includes("[");
  let arrayCloseBool = label.includes("]");

  //console.log(obj, label,arrayOpenBool && arrayCloseBool);

  if (arrayOpenBool && arrayCloseBool) {
    let start = label.split("[")[0];
    let number = label.split("[")[1].split("]")[0];
    let end = label.split("]")[0];
    if (label.includes(".")) end = label.split(".")[1];
    return obj[start][number]
      ? returnElement(obj[start][number], end)
      : undefined;
  }

  if (pointBool) {
    let start = label.split(".")[0];
    let end = label.split(".")[1];
    //console.log(obj, label, start, end, obj[end]);
    if (start === "") return obj[end];
    return returnElement(obj[start], end);
  }

  return obj[label];
}


var a = {
  _id: "5d406a179f35ed326a6a5567",
  age: 28,
  name: {first: "James",last: "Bond"},
  user: [{first: "Jon",last: "Witch"},{first: "Myra",last: "Navarro",number:[0,10]}]
};
var b = [];
b.push("item");//undefined
b.push("_id");//5d406a179f35ed326a6a5567
b.push("age");//28
b.push("name.first");//James
b.push("user[1]");//obj{}
b.push("user[1].first");//Myra
b.push("user[2].first");//undefined
b.push("user[1].email");//undefined
b.push("user[0].number");//[0, 1]
b.push("user[1].number[1]");//1

b.forEach(el => {
  console.log(returnElement(a, el));
})

Edit:

Here is an additional thing, given the solution proposed by @NinaScholz, it allows you to sort the data you more parameters, if it can be of use to someone.

based on the following solution: Link

let datatable = [
      {
        _id: '5d406a171ed43384972f04b5',
        index: 0,
        age: 28,
        eyeColor: 'brown',
        name: {
          first: 'Myra',
          last: 'Navarro',
        },
        company: 'SUSTENZA',
        email: 'myra.navarro@sustenza.net',
      },
      {
        _id: '5d406a170db0f4b04d9a9acf',
        index: 1,
        age: 23,
        eyeColor: 'blue',
        name: {
          first: 'Harriett',
          last: 'Tanner',
        },
        company: 'VALPREAL',
        email: 'harriett.tanner@valpreal.com',
      },
      {
        _id: '5d406a17e95da8ff80a759c5',
        index: 2,
        age: 39,
        eyeColor: 'blue',
        name: {
          first: 'Vega',
          last: 'Hanson',
        },
        company: 'BEDLAM',
        email: 'vega.hanson@bedlam.tv',
      },
      {
        _id: '5d406a175505da190e6875ec',
        index: 3,
        age: 31,
        eyeColor: 'blue',
        name: {
          first: 'Rosemary',
          last: 'Fields',
        },
        company: 'QUAILCOM',
        email: 'rosemary.fields@quailcom.me',
      },
      {
        _id: '5d406a17ea96044c027f4e50',
        index: 4,
        age: 27,
        eyeColor: 'brown',
        name: {
          first: 'Dale',
          last: 'Wilkinson',
        },
        company: 'QIAO',
        email: 'dale.wilkinson@qiao.org',
      },
      {
        _id: '5d406a17c5fff1ff6653a555',
        index: 5,
        age: 25,
        eyeColor: 'blue',
        name: {
          first: 'Beatrice',
          last: 'Contreras',
        },
        company: 'ZENOLUX',
        email: 'beatrice.contreras@zenolux.us',
      },
      {
        _id: '5d406a17a199efcba25e1f26',
        index: 6,
        age: 34,
        eyeColor: 'blue',
        name: {
          first: 'Hancock',
          last: 'Wynn',
        },
        company: 'PLASMOS',
        email: 'hancock.wynn@plasmos.co.uk',
      },
      {
        _id: '5d406a17019a2a4544a4f134',
        index: 7,
        age: 40,
        eyeColor: 'blue',
        name: {
          first: 'Beatrice',
          last: 'Aston',
        },
        company: 'SNACKTION',
        email: 'beatrice.aston@snacktion.name',
      },
      {
        _id: '5d406a17e516dd71af8210d4',
        index: 8,
        age: 39,
        eyeColor: 'blue',
        name: {
          first: 'Barnes',
          last: 'Dunn',
        },
        company: 'PORTALINE',
        email: 'barnes.dunn@portaline.ca',
      },
      {
        _id: '5d406a17516936a025b73c33',
        index: 9,
        age: 34,
        eyeColor: 'green',
        name: {
          first: 'Blanche',
          last: 'Cherry',
        },
        company: 'ISOSWITCH',
        email: 'blanche.cherry@isoswitch.io',
      },
      {
        _id: '5d406a17527a4d2c6a7897dd',
        index: 10,
        age: 33,
        eyeColor: 'blue',
        name: {
          first: 'Gilliam',
          last: 'Farley',
        },
        company: 'AMTAS',
        email: 'gilliam.farley@amtas.biz',
      },
      {
        _id: '5d406a175ff11478c416c30b',
        index: 11,
        age: 26,
        eyeColor: 'brown',
        name: {
          first: 'Laura',
          last: 'Short',
        },
        company: 'FISHLAND',
        email: 'laura.short@fishland.info',
      },
      {
        _id: '5d406a1738181b471847339a',
        index: 12,
        age: 20,
        eyeColor: 'brown',
        name: {
          first: 'Moreno',
          last: 'Barber',
        },
        company: 'KEENGEN',
        email: 'moreno.barber@keengen.net',
      },
      {
        _id: '5d406a17a6bcae6fe3ad1735',
        index: 13,
        age: 30,
        eyeColor: 'brown',
        name: {
          first: 'Fischer',
          last: 'French',
        },
        company: 'INCUBUS',
        email: 'fischer.french@incubus.com',
      },
      {
        _id: '5d406a17600ca53e8f63f263',
        index: 14,
        age: 30,
        eyeColor: 'brown',
        name: {
          first: 'Donaldson',
          last: 'Carr',
        },
        company: 'SUNCLIPSE',
        email: 'donaldson.carr@sunclipse.tv',
      },
      {
        _id: '5d406a17530655789a27174f',
        index: 15,
        age: 35,
        eyeColor: 'green',
        name: {
          first: 'Sophia',
          last: 'Payne',
        },
        company: 'PRISMATIC',
        email: 'sophia.payne@prismatic.me',
      },
      {
        _id: '5d406a175dbc687b4c7669d8',
        index: 16,
        age: 34,
        eyeColor: 'green',
        name: {
          first: 'Simone',
          last: 'Pollard',
        },
        company: 'DIGIGEN',
        email: 'simone.pollard@digigen.org',
      },
      {
        _id: '5d406a179f35ed326a6a5567',
        index: 17,
        age: 28,
        eyeColor: 'green',
        name: {
          first: 'Yvette',
          last: 'Daugherty',
        },
        company: 'CHILLIUM',
        email: 'yvette.daugherty@chillium.us',
      },
    ];

function getValue(object, path) {
    return path
        .replace(/\[/g, '.')
        .replace(/\]/g, '')
        .split('.')
        .reduce((o, k) => (o || {})[k], object);
}

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (getValue(a, property) < getValue(b, property)) ? -1 : (getValue(a, property) > getValue(b, property)) ? 1 : 0;
        return result * sortOrder;
    }
}

function dynamicSortMultiple() {
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

function dynamicSortMultipleRic() {
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        while(result === 0 && i < numberOfProperties) result = dynamicSort(props[i++])(obj1, obj2);
        return result;
    }
}

var copyA = Object.assign([], datatable);
var copyB = Object.assign([], datatable);
var copyC = Object.assign([], datatable);

let a = copyA.sort(dynamicSort("name.first"));
let b = copyB.sort(dynamicSortMultiple("name.first","name.last"));
let c = copyC.sort(dynamicSortMultipleRic("name.first","name.last"));


console.log(a,b,c)
Paul
  • 3,644
  • 9
  • 47
  • 113
  • It looks like *"the poor man's"* Regex. – zer00ne Jul 30 '19 at 19:20
  • @zer00ne: Sorry, I'm not able to understand what you would like to say. I can ask you to be more specific. – Paul Jul 30 '19 at 19:23
  • Regex is a set of characters that express a search pattern. Many new developers attempt to use Regex for purposes it wasn't really meant for. You are searching the string representation of an object which is like swimming in mud. – zer00ne Jul 30 '19 at 19:32

1 Answers1

3

You could replace the brackets and split the string and get the values form the given object.

function getValue(object, path) {
    return path
        .replace(/\[/g, '.')
        .replace(/\]/g, '')
        .split('.')
        .reduce((o, k) => (o || {})[k], object);
}


var a = { _id: "5d406a179f35ed326a6a5567", age: 28, name: { first: "James", last: "Bond" }, user: [{ first: "Jon", last: "Witch" }, { first: "Myra", last: "Navarro", number: [0, 10] }] };

var b = [];

b.push("item");//undefined
b.push("_id");//5d406a179f35ed326a6a5567
b.push("age");//28
b.push("name.first");//James
b.push("user[1]");//obj{}
b.push("user[1].first");//Myra
b.push("user[2].first");//undefined
b.push("user[1].email");//undefined
b.push("user[1].number");//[0, 1]
b.push("user[1].number[1]");//1

b.forEach(el => {
  console.log(getValue(a, el));
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • That's a really nice solution. – Mark Jul 30 '19 at 19:40
  • I guess I won't post my almost identical solution. Nina, you're just too fast for me! – Scott Sauyet Jul 30 '19 at 19:41
  • @nina: Very interesting as a solution, I was going crazy to solve my solution. – Paul Jul 30 '19 at 19:59
  • @ScottSauyet: Publish your solution would be very interesting to see your kind of approach. – Paul Jul 30 '19 at 19:59
  • @nina: I didn't understand what you mean by: You could replace the brackets and split the string and get the values form the given object. – Paul Jul 30 '19 at 20:01
  • for example `'user[1].number[1]'` is replaced to `'user.1.number.1'` and this is splitted to an array `['user', '1', 'number', '1']`. then this array is reduced and used as keys by returning the property. – Nina Scholz Jul 30 '19 at 20:13
  • @Paul, when I said it was almost identical, I meant it. The only difference outside variable names was that I used an arrow function. It's definitely not worth posting after this one. – Scott Sauyet Jul 31 '19 at 01:04
  • @NinaScholz: Thank you very much, one last thing. I have an array of those data, which I would like to sort by attribute. The problem that I would like the data to be sorted by sub-attribute, so I was wondering if there is a way using the function you indicated to make it possible to do it? – Paul Jul 31 '19 at 05:53
  • @NinaScholz: For example, I did this: https://jsbin.com/juxurecejo/1/edit?js,console Sort the data by desc age, as you can see. I would like to try to sort the data for example by "name.first" or "-name.last". Do you think we can do or talk about something that would take too long to sort? – Paul Jul 31 '19 at 05:57
  • you could replace `a[property]` with `getValue(a, property)` for deeper nested properties. if you have a large data set, you might have a look into [sorting with map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Sorting_with_map) and take the value for sorting with a single access for every item. – Nina Scholz Jul 31 '19 at 06:03
  • @NinaScholz: The solution that indicates you, that of replacement, does not seem to work. https://jsbin.com/rosuqiqiye/2/edit?js,console – Paul Jul 31 '19 at 07:24
  • @NinaScholz: I'm not understanding, the tried several times and gave me strange results did not order them, now it seems to work. – Paul Jul 31 '19 at 07:34
  • @NinaScholz: I updated the ask, adding a solution you never know could be useful to someone, it allows you to sort data on multiple parameters. Let me know what you think. ;) – Paul Jul 31 '19 at 07:57
  • i would use a shorter approach for sorting by taking the values only once: `return function (a, b) { var aa = getValue(a, property), bb = getValue(b, property), result = +(aa > bb) || -(aa < bb); return result * sortOrder; }` – Nina Scholz Jul 31 '19 at 08:33