Walk through a nested array using index in JavaScript - javascript

I want walk through a nested array and need to find the target element in the array. An example path [2, 1] should return {text: 'More 2'} and path [2, 2, 1] should return { text: 'Other-2' }. I tried lodash functions but no luck yet.
My Nested array is given below:
var data = [
{ text: 'Item 1', },
{ text: 'Item 2', },
{
text: 'More',
children: [
{ text: 'More 1', children: [] },
{ text: 'More 2'},
{ text: 'Other', children:[ {text: 'Other-1'}, {text: 'Other-2'}, {text: 'Other-3'} ] }
]
}
];

Well, it's not a multi-dimensional array, nor is it a raggedy array-of-arrays. It's an array of objects (that happen contain other arrays of objects that happen to...).
Lodash's _.get() ought to do the trick for you:
const _ = require('lodash');
const data = data = [
{ text: 'Item 1', },
{ text: 'Item 2', },
{
text: 'More',
children: [
{ text: 'More 1', children: [] },
{ text: 'More 2'},
{ text: 'Other', children:[ {text: 'Other-1'}, {text: 'Other-2'}, {text: 'Other-3'} ] }
]
}
];
const widget = _.get(obj, '[2].children[1]');
console.log('widget',widget);
Or... roll your own. It's not that hard to walk the tree:
function select(data, ...path) {
let i = path.shift() ;
let node = data[i] ;
while ( node && (i=path.shift()) !== undefined ) {
node = node?.children?.[i] ;
}
return node ;
}
const widget = select( data, 2, 1 );
console.log(widget);

Related

Remove an object in array from array

I want to delete the 1 ids of cardItems of my list with 0 ids and keep the order of the lists. what is the best way?
lists: [
{
id: '0',
title: 'LIST 1',
cardItems: [
{
id: '0',
text: 'Card 1',
},
{
id: '1',
text: 'Card 2',
},
{
id: '2',
text: 'Card 3',
},
],
},
]
You can use .find to get the list item by id, and then remove the card item using .filter:
const lists = [
{
id: '0',
title: 'LIST 1',
cardItems: [
{ id: '0', text: 'Card 1' },
{ id: '1', text: 'Card 2' },
{ id: '2', text: 'Card 3' },
],
},
];
const removeCardItem = (list, listItemId, cardItemId) => {
const arr = [...list];
// get list item by id
const item = arr.find(listItem => listItem.id === listItemId);
// remove card item by id if found
if(item)
item.cardItems = item.cardItems.filter(cardItem =>
cardItem.id !== cardItemId
);
return arr;
}
console.log( removeCardItem(lists, '0', '1') );
Something similar to
if(lists[0].cardItems[0].id === 1){
lists[0].cardItems.splice(0,1);
}
Obviously this will only check that one value, but this can easily be implemented into a loop or nested loops or whatever you need. (I can't know since I can't see all of your code)
Your question is a little bit hard to understand, but this was my best guess at helping you out! If this wasn't the answer you're looking for then please give us more information so we can help you more effectively!

JavaScript: Add new attribute to object in an array

I am trying to add an item into an existing object in an array (index each array):
const dataInput = [
{ title: 'first', description: 'test 1' },
{ title: 'second', description: 'test 1' },
]
This is what I've tried:
dataInput.map((data, index) => {
availableItems.push({'idx':index})
})
This pushes a new object instead of adding the element to the existing first and second.
[
{ title: 'first', description: 'test 1' },
{ title: 'second', description: 'test 1' },
{idx:0},
{idx:1}
]
How could I achieve that? (below is what I need)
[
{ title: 'first', description: 'test 1', idx: 0 },
{ title: 'second', description: 'test 1', idx:1 },
]
You need to add a new attribute at each iteration:
const dataInput = [
{ title: 'first', description: 'test 1' },
{ title: 'second', description: 'test 1' },
];
const res = dataInput.map( (data, index) => ({...data, idx:index}) );
console.log(res);
Another option:
dataInput.forEach((element, index) => (element["idx"] = index));
Another option:
const dataInput= [
{ title: 'first', description: 'test 1' },
{ title: 'second', description: 'test 1' },
]
const result = dataInput.reduce((acc, cur, index) => {
acc.push({...cur, idx: index})
return acc
},[])
console.log(result)

How to filter an array in ReactJs by comparing it with another array

I have two arrays in ReactJS as follows
let document = [
{ text: 'Document 1', value: 'abcd' },
{ text: 'Document 2', value: 'efgh' }
]
let filterTypes = [{ value: 'abcd', id: 1 }]
How to generate the filtered array from this in ReactJS containing just one object with value abcd?
You could use Array.prototype.some() method inside Array.prototype.filter() method. Some method returns a Boolean value if at least one item in the array
passes the test by the given callback function.
const doc = [
{ text: 'Document 1', value: 'abcd' },
{ text: 'Document 2', value: 'efgh' },
];
const filterTypes = [{ value: 'abcd', id: 1 }];
const ret = doc.filter((x) => filterTypes.some((y) => y.value === x.value));
console.log(ret);
const docArray = [
{ text: 'Document 1', value: 'abcd' },
{ text: 'Document 2', value: 'efgh' },
];
const filterTypes = [{ value: 'abcd', id: 1 }];
console.log('-----non-matched----');
const nonmatched = docArray.filter(doc => filterTypes.findIndex(filt=> filt.value === doc.value));
console.log(nonmatched);
console.log('------matched----');
const matched = docArray.filter(doc => filterTypes.findIndex(filt=> filt.value !== doc.value));
console.log(matched);

Javascript how to get an array depth

Array like this:
const array = [
{
title: 'xx',
children: [
{
title: 'xxx',
children: [
{ title: 'xxx' }
]
}
]
}
]
The depth is 3, how i get depth use a function, or make array become this
const array = [
{
title: 'xx',
depth: 1,
children: [
{
title: 'xxx',
depth: 2,
children: [
{ title: 'xxx', depth: 3 }
]
}
]
}
]
Is there a better way in javascript?
You could use a simple recursive function to decorate the children at each level.
const array = [
{
title: 'Title 1',
children: [
{
title: 'Title 2',
children: [
{
title: 'Title 3'
}
]
}
]
}
];
const depthArray = depthDecorator(array);
console.log(depthArray);
function depthDecorator(array, depth = 1) {
return array.map((child) => Object.assign(child, {
depth,
children: depthDecorator(child.children || [], depth + 1)
}));
}

Complicated array merging (keeping order)

I've got two arrays as follows:
const array1 = [
{
id: 'a1',
text: 'some text'
},
{
id: 'a2',
text: 'some more text',
},
{
id: 'a3',
text: 'some more text',
},
]
and
const array2 = [
{
id: 'a1',
text: 'some text'
},
{
id: 'ab12',
text: 'some text'
},
{
id: 'abc123',
text: 'some further text'
},
{
id: 'a3',
text: 'some more text'
},
{
id: 'bx44',
text: 'some more text'
},
]
I would like to combine these arrays with information has to whether each item has a "matching" 'id' property as the other array, so:
combined = [
{
id: 'a1',
text: 'some text',
info: 'in-both'
},
{
id: 'a2',
text: 'some text',
info: 'only-array1',
},
{
id: 'ab12',
text: 'some text',
info: 'only-array2',
},
{
id: 'abc123',
text: 'some further text',
info: 'only-array2',
},
{
id: 'a3',
text: 'some more text',
info: 'in-both',
},
{
id: 'bx44',
text: 'some more text',
info: 'only-array2',
},
]
I'm trying to keep the "inherent" order, so that items being only present in array1 or array2 end up between matches (items in both arrays) relative to their index. For example, 'a2' (only present in array1) comes after 'a1' but before 'a3'. If, between matches, there are multiple items being present only in array1 or array2, I'm trying to achieve so that the ones belonging to array1 come first (in the example, 'a2' comes before 'ab12' and 'abc123').
The code so far:
array1.reduce((all, curr, a1index, a1array) => {
let correspondingItemInArray2Index = array2.findIndex(a2item => a2item.id === curr.id);
if(correspondingItemInArray2Index === -1) {
curr.info = 'only-in-array1';
}
else if(correspondingItemInArray2Index === a1index) {
// Items are on same level...
curr.info = 'in-both';
}
else {
... // I need to find all items of array2 until the next 'match' of ids?
}
}
, []);
You could get common items and iterate all between.
function merge(...data) {
var common = data.map(a => a.map(({ id }) => id)).reduce((a, b) => a.filter(v => b.includes(v))),
indices = data.map(_ => 0),
result = [];
while (indices.every((l, i) => l < data[i].length)) {
indices = indices.map((j, i) => {
while (j < data[i].length && !common.includes(data[i][j].id)) {
result.push(Object.assign({}, data[i][j++], { info: ['a', 'b'][i] }));
}
return j;
});
if (indices.some((l, i) => l >= data[i].length)) break;
result.push(Object.assign({}, data[0][indices[0]], { info: 'both' }));
indices = indices.map(v => v + 1);
}
indices.forEach((j, i) => {
while (j < data[i].length) {
result.push(Object.assign({}, data[i][j++], { info: ['a', 'b'][i] }));
}
});
return result;
}
var array1 = [{ id: 'a1', text: 'some text' }, { id: 'a2', text: 'some more text' }, { id: 'a3', text: 'some more text' }],
array2 = [{ id: 'a1', text: 'some text' }, { id: 'ab12', text: 'some text' }, { id: 'abc123', text: 'some further text' }, { id: 'a3', text: 'some more text' }, { id: 'bx44', text: 'some more text' }],
result = merge(array1, array2);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories