0

I have an array:

let ar = [{
   asst: 1,
   v: 'b'
 }, {
   emp: 4
 }, {
   journal_id: 3
 }, {
   asst: 4
 }, {
   asst: 1,
   v: 'a'
 }, {
   asst: 1,
   v: 'c'
 }, {
   journal_id: 3
 }, {
   journal_id: 3
 }]

I want an array that has asst and journal_id as array of arrays and emp as just an object in the array that has array of asst and journal_id. Like this:

[[{asst:1, v: 'a'}, {asst:1, v: 'b'},{asst:1, v: 'c'}], [{asst:4}], [{journal_id:3}, {journal_id:3}, {journal_id:3}], {emp:4}]

I have tried this:

let ar = [{
    asst: 1,
    v: 'b'
}, {
    emp: 4
}, {
    journal_id: 3
}, {
    asst: 4
}, {
    asst: 1,
    v: 'a'
}, {
    asst: 1,
    v: 'c'
}, {
    journal_id: 3
}, {
    journal_id: 3
}]
let asstArray = [],
    journalArray = [],
    fullArray = [];

for (let i = 0; i < ar.length; i++) {
    debugger
    if (ar[i].asst) {
        let contains = false;
        for (let j = 0; j < asstArray.length; j++) {
            for (let k = 0; k < asstArray[j].length; k++) {
                if (asstArray[j][k].asst == ar[i].asst) {
                    contains = true;
                    let d = asstArray[j][k];
                }
            }
            if (contains) {
                asstArray[j].push(ar[i]);
            }
        }
        if (!contains) {
            asstArray.push([ar[i]]);
        }
    } else if (ar[i].journal_id) {
        let contains = false;
        for (let j = 0; j < journalArray.length; j++) {
            for (let k = 0; k < journalArray[j].length; k++) {
                if (journalArray[j][k].journal_id == ar[i].journal_id) {
                    contains = true;
                }
            }
            if (contains) {
                journalArray[j].push(ar[i]);
            }
        }
        if (!contains) {
            journalArray.push([ar[i]]);
        }
    }
}
fullArray.push(asstArray);
fullArray.push(journalArray);
console.log(fullArray, "Full")

JS Fiddle

3 Answers 3

3

Here is a succint way to do it with reduce and Object.values. Also, the keys to check are declared in the initial value to the reduce function.

By using ES6 desctructuring, you can then rebuild the array you want at the end, with emp, out of the inner arrays.

With emp in the array:

const ar = [
  { asst: 1, v: 'b' },
  { emp: 4 },
  { journal_id: 3 },
  { asst: 4 },
  { asst: 1, v: 'a' },
  { asst: 1, v: 'c' },
  { journal_id: 3 },
  { journal_id: 3 }
];

const result = Object.values(ar.reduce((accum, e) => {
  Object.keys(accum).forEach(k => {
    if (k in e) accum[k].push(e);
  });
  return accum;
}, { asst: [], journal_id: [], emp: [] }));

console.log(result);

With emp outside the inner array:

const ar = [
  { asst: 1, v: 'b' },
  { emp: 4 },
  { journal_id: 3 },
  { asst: 4 },
  { asst: 1, v: 'a' },
  { asst: 1, v: 'c' },
  { journal_id: 3 },
  { journal_id: 3 }
];

let result = ar.reduce((accum, e) => {
  Object.keys(accum).forEach(k => {
    if (k in e) accum[k].push(e);
  });
  return accum;
}, { asst: [], journal_id: [], emp: [] });

const { emp, ...otherProps } = result;
result = [...Object.values(otherProps), emp[0]];

console.log(result);

Sign up to request clarification or add additional context in comments.

5 Comments

i don't want emp to be inside an array. i want it to be just an object
Yes, updated, emp is now out: [ [ { "asst": 1, "v": "b" }, { "asst": 4 }, { "asst": 1, "v": "a" }, { "asst": 1, "v": "c" } ], [ { "journal_id": 3 }, { "journal_id": 3 }, { "journal_id": 3 } ], { "emp": 4 } ]
thank you but i dont know how many objects i will have like emp. so it won't work. im sorry for un accepting your answer
Well, I can edit and put emp back in the array, the code will be even shorter, you now have both versions, and very short code
@Le guy, You should reedit your question then to reflect that
2

You could combine the values of the wanted grouping keys to a single key and group by this value.

Objects without grouping keys are pushed to the result set directly.

var array = [{ asst: 1, v: 'b' }, { emp: 4 }, { journal_id: 3 }, { asst: 4 }, { asst: 1, v: 'a' }, { asst: 1, v: 'c' }, { journal_id: 3 }, { journal_id: 3 }], keys = ['asst', 'journal_id'],
    keys = ['asst', 'journal_id'],
    result = array.reduce((hash => (r, o) => {
        if (keys.some(k => k in o)) {
            var key = keys.map(k => o[k]).join('|');
            if (!hash[key]) {
                r.push(hash[key] = []);
            }
            hash[key].push(o);
        } else {
            r.push(o);
        }
        return r;
    })({}), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

10 Comments

i don't want emp to be inside an array. i want it to be just an object
yould you have more than one object with emp?
yes i will have more than one emp and others like emp that aren't asst or journal_id
i dont want those that aren't asst or journal_id to be an array inside the array
do you need a special order as well?
|
2

You can reduce the array in a Map and then create a new array with the Map values:

const data = [{"asst":1,"v":"b"},{"emp":4},{"journal_id":3},{"asst":4},{"asst":1,"v":"a"},{"asst":1,"v":"c"},{"journal_id":3},{"journal_id":3}];


const grouped = data.reduce(
  (result,item)=>{
    //key is item.asst or item.jornal_id or other
    const key = item.asst || item.journal_id || 'other';
    //set result(key) with empty array or existing array and conat new item
    return result.set(key,(result.get(key)||[]).concat(item));
  },new Map()
);
//get other values or empty array if they don't exist:
const others = grouped.get('other') || [];
//remove others if they exist:
grouped.delete('other');

//log array from Map values
console.log(others.concat([...grouped.values()]));

2 Comments

i don't want emp to be inside an array. i want it to be just an object
@Leguy Updated answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.