Constructing alphabetized array of objects - javascript

I have an array of objects with a name property...
var myList = [{
name: 'Apple'
}, {
name: 'Nervousness',
}, {
name: 'Dry'
}, {
name: 'Assign'
}, {
name: 'Date'
}]
Essentially, I am trying to create an array set up like this:
[{
name: 'A',
items: [{
name: 'Apple'
}, {
name: 'Assign'
}]
}, {
name: 'D',
items: [{
name: 'Date',
}, {
name: 'Dry',
}]
}, {
name: 'N',
items: [{
name: 'Nervousness',
}]
}];
Basically, my array of objects needs to be alphabetized, placed into a new object with a parent key/value of 'name' with the corresponding letter.
I can alphabetize them as follows...
myList.sort(function (a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
});
Then I can create an array of the first letters...
var headerLetters = [];
angular.forEach(myList, function (item) {
var firstLetter = item.name.charAt(0);
if (headerLetters.indexOf(firstLetter) === -1) {
headerLetters.push(firstLetter);
}
});
But then this is where I am stuck... I can check for duplicate first letters, but then how would I iterate through my list of objects and push them into a new object array in alphabetical order?

Assuming you sort them alphabetically first then you can always just check the latest item in the array and see if it matches the current name.
var headerLetters = [];
angular.forEach(myList, function(item) {
var firstLetter = item.name[0];
var lastObj = headerLetters[headerLetters.length - 1];
if (!lastObj || lastObj.name !== firstLetter) {
lastObj = {
name: firstLetter,
items: []
};
headerLetters.push(lastObj);
}
lastObj.items.push(item);
});

Related

Find the unique id of the item and group its value in array using reduce method?

Please help me to find the expected output from the given scenario
input array:
const items = [
{ id: 1, name: "a" },
{ id: 2, name: "b" },
{ id: 3, name: "c" },
{ id: 1, name: "d" },
{ id: 3, name: "f" },
{ id: 1, name: "a" },
{ id: 3, name: "c" },
]
expected output:
[{ id: 1, names: ['a', 'd']},
{ id: 2, names: ['b']},
{ id: 3, names: ['c', 'f']}]
You can create a new array, loop through your main array and check if there is an object with the current id in the new array and update it or create a new object accordingly.
Like this:
let newItems = [];
items.forEach(item => {
let index = newItems.findIndex(el => el.id == item.id);
if (index > -1) {
if (newItems[index]['names'].indexOf(item.name) === -1) {
return newItems[index]['names'].push(item.name)
}
} else {
newItems.push({id: item.id, names: [item.name]});
}
});
With reduce method:
const newArr = items.reduce((pv, cv) => {
let index = pv.findIndex(el => el.id == cv.id);
if (index > -1) {
if (pv[index]['names'].indexOf(cv.name) === -1) {
pv[index]['names'].push(cv.name)
}
} else {
pv.push({id: cv.id, names: [cv.name]});
}
return pv;
}, []);
pv is previous value which is the new array, cv is current value which is each object in items array. Initial value of newArr is []
You can use spread operator and retrieve the values of the duplicate key and push it in the new array of objects.
Thanks & Regards

How to update a value in nested array based on the given index and return original array in javascript?

I have an index '3_1_0' and the following array:-
var fields = [
{
name: 'a'
},
{
name: 'b'
},
{
name: 'c'
},
{
name: 'd',
fields: [
{
name: 'd1'
},
{
name: 'd2',
fields: [
{
name: 'd2.1'
}
]
}
]
}
]
I need to extract the element from the above fields array based on the index. so 3_1_0 will extract following
{
name: 'd2.1'
}
Update the value from d2.1 to some other value like 'new_d2.1' and attach the updated value at the same index in original fields array and return the updated fields array. How this can be done?
You can use Array.reduce to get the desired result. We start by splitting the index into an array, then reducing to get the result.
We'll use some Optional Chaining to ensure we'll return undefined if no value is found (say our index was '7_10_20').
Once we've found our object, we can set the required property.
const fields = [ { name: 'a' }, { name: 'b' }, { name: 'c' }, { name: 'd', fields: [ { name: 'd1' }, { name: 'd2', fields: [ { name: 'd2.1' } ] } ] } ];
const index = '3_1_0'
function setValue(fields, index, property, value) {
const obj = index.split('_').reduce((acc, key) => {
return acc?.[key] || acc?.fields?.[key];
}, fields);
// Only update if we actually find anything
if (obj) {
obj[property] = value
}
}
setValue(fields, '3_1_0', 'name', 'new_d2.1');
console.log("Fields:", fields);
const data = [{ name: 'a' }, { name: 'b' }, { name: 'c' }, { name: 'd', fields: [ { name: 'd1' }, { name: 'd2', fields: [ { name: 'd2.1' } ] } ] } ];
let givenIdxs = "3_1_0";
let indexes = givenIdxs.split("_");
let result = data[indexes[0]];
for(let idx = 1; idx < indexes.length; idx++){
result = result.fields[indexes[idx]];
}
console.log(result);

How to get index of a 2d array of 2 similar structure ones with same value

Sorry the title may not present well.
I got two 2d arrays with similar structure.
array A:
arrayA[0]['account_name'] = 'a0';
arrayA[1]['account_name'] = 'a1';
arrayA[2]['account_name'] = 'a2';
And array B:
arrayB[0]['account_name'] = 'a1';
arrayB[1]['account_name'] = 'b0';
arrayB[2]['account_name'] = 'c0';
arrayB[3]['account_name'] = 'a0';
arrayB[4]['account_name'] = 'd3';
arrayB[5]['account_name'] = 'e8';
arrayB[6]['account_name'] = 'a3';
arrayB[7]['account_name'] = 'b4';
arrayB[8]['account_name'] = 'b1';
Now I know arrayA[0]['account_name'] equals to "a0", how can I search efficiently to check if it also exists in array B / know its position in array B? And I would like to loop for all values in array A.
const a = [
{ name: 'a0' },
{ name: 'a1' },
{ name: 'b2' }
];
const b = [
{ name: 'a0' },
{ name: 'a1' },
{ name: 'a2' },
{ name: 'b0' },
{ name: 'b1' },
{ name: 'b2' }
];
a.forEach((aa, i) => {
let found;
b.forEach((bb, j) => {
if(aa.name === bb.name) {
found = {
index: j,
value: aa.name
};
return true;
}
});
console.log(found);
});

Unlimited Deep Search with lodash

I have a dynamic array of objects which has an unlimited nested array of items in it like below:
var items = [{
id: '7172hsdr',
item: {},
items: []
},
{
id: '5343rtas',
item: {},
items: [{
id: '4545nrhk',
item: [],
items: [{
id: 'kbkb1212',
item: [],
items: []
}]
}]
}]
I want to search in this collection and find an object with id kbkb1212. I prefer to do it with lodash.
The problem is sometimes I look for an object with id of 7172hsdr, and sometimes I need kbkb1212 for instance.
What I've done
I have used below function which search the first level.
var item = _.find(items, { id: '7172hsdr' });
It works fine, but If I need kbkb1212 it does not.
In plain Javascript you could use an interative and recursive approach for finding an item in a nested data structure.
function find(array, id) {
var object;
array.some(function f(a) {
if (a.id === id) {
object = a;
return true;
}
if (Array.isArray(a.items)) {
return a.items.some(f);
}
});
return object;
}
var items = [{ id: '7172hsdr', item: {}, items: [] }, { id: '5343rtas', item: {}, items: [{ id: '4545nrhk', item: [], items: [{ id: 'kbkb1212', item: [], items: [] }] }] }];
console.log(find(items, '7172hsdr'));
console.log(find(items, 'kbkb1212'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
It's not universal solution, but it works for your case
function deepFind(array, id) {
return array.reduce(function(result, arrayItem) {
if (result.length) return result;
if (arrayItem.id === id) return result.concat([arrayItem]);
return arrayItem.items.length ? deepFind(arrayItem.items, id) : result;
}, [])
}
console.log('one', deepFind(items, 'kbkb1212')[0]);
console.log('two', deepFind(items, '7172hsdr')[0]);
https://jsfiddle.net/v8kpr83b/3/
Pure Javascript solution using a custom recursive function:
var items = [{ id: '7172hsdr', item: {}, items: [] }, { id: '5343rtas', item: {}, items: [{ id: '4545nrhk', item: [], items: [{ id: 'kbkb1212', item: [], items: [] }] }] }];
function getObjById(items, id) {
var i = 0, o;
for (i = 0, len = items.length; i < len; i++) {
o = items[i];
if (o['id'] && o.id == id) {
return o;
} else if (o['items'] && Array.isArray(o.items) && o.items.length){
return getObjById(o.items, id);
}
}
}
console.log(getObjById(items, 'kbkb1212'));
console.log(getObjById(items, '7172hsdr'));

using javascript filter() with a flag

I want to return arr2 but want to prompt the user whether there's changes or not by comparing it with arr. with below's approach, I got id of undefined if arr2 have any missing item.
var arr = [{
id: 1,
name: 'something'
}, {
id: 2,
name: 'something2'
}]
var arr2 = [{
id: 1,
name: 'something'
}]
var result = arr.filter(function(obj, i) {
return obj.id == arr2[i].id;
});
document.write(JSON.stringify(result))
The problem in your code is that arr[1] is undefined and you are trying to get id property of undefined. Now what you can do is, get id's in array then get index and check based on that in filter.
var arr = [{
id: 1,
name: 'something'
}, {
id: 2,
name: 'something2'
}]
var arr2 = [{
id: 1,
name: 'something'
}];
var arrIds = arr2.map(function(v) {
return v.id;
});
var result = arr.filter(function(obj) {
var i = arrIds.indexOf(obj.id);
return i > -1 &&
obj.name == arr2[i].name; // check name property here
});
document.write(JSON.stringify(result))
Loop through arr2 in a callback of the .filter to test each item of arr2.
var arr = [{
id: 1,
name: 'something'
}, {
id: 2,
name: 'something2'
}]
var arr2 = [{
id: 1,
name: 'something'
}, {
id: 5,
name: 'something'
}, {
id: 8,
name: 'something'
}];
var isValInArr = function(arr, key, val) {
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i][key] === val) {
return true;
}
}
return false;
};
var result = arr.filter(function(obj, i) {
return isValInArr(arr2, 'id', obj.id);
});
document.write(JSON.stringify(result))

Categories

Resources