Unable to get index of an object in array - javascript

I thought if I maintain the original reference than I would simply get the index
const selected = {id: "abcd123", quantity: "5"};
const location = [
{id: "abcd123", quantity: "3"},
{id: "abcd1234", quantity: "3"},
];
const filterLocation = location.filter(loc => loc.id === selected.id);
console.log(location.indexOf(filterLocation));
I expect it would log 0 but it always return -1. How it actually works?

First of all the filterLocation does not include any object identical to the location. It includes the only object with the same id field but the quantity field is different. Secondly the indexOf method does not work properly for non-scalar arguments.

const selected = {id: "abcd123", quantity: "5"};
const location = [
{id: "abcd123", quantity: "3"},
{id: "abcd1234", quantity: "3"},
];
const filterLocation = location.filter(loc => loc.id === selected.id);
console.log(location.findIndex(value => value.id === filterLocation[0].id )));
filter return a new array. So, you just need access to that value filtered in this example
change indexOf for findIndex. location is an array of objects so you need to iterate all the array again for recover the index. Sure, it's just for this example, also you could recover the index in the same filter operation.
console.log(location.findIndex(value => value.id === filterLocation[0].id )));

Sorry my mistake
I think I should switch to findIndex instead of indexOf.
const selected = {id: "abcd123", quantity: "5"};
const location = [
{id: "abcd123", quantity: "3"},
{id: "abcd1234", quantity: "3"},
];
const filterLocation = location.filter(loc => loc.id === selected.id);
console.log(location.findIndex(loc => loc.id === selected.id));
Then I would get the specified index that I need.

Related

How to group array of object by key value pairs using javaScript?

I just started learning JavaScript, I have this type of array, how I can turn this array of objects into key-value pairs like below, Any source and reference is acceptable.
Sample Array:
[
{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},
{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}
]
Expected Result:
{
"6d7e75e6-c58b-11e7-95-ac162d77eceb":1,
"6d2e75e6-c58b-11e7-95-ac162d77eceb":1
}
Using Array.prototype.Reduce:
const arr = [{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}];
const result = arr.reduce((acc, { Id, qty }) => ({ ...acc, [Id]: qty }), {});
console.log(result);
Another approach, a little more beginner friendly.
const arr = [
{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},
{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}
];
const newObject = {}; // empty object
// loop over each element of the array
arr.forEach(element => {
// the key is the element identifier (Id) and the value is the element quantity (qty)
newObject[element.Id] = element.qty;
});
You can use a loop and add the item.Id as the key and the item.qty as the value in an empty object.
let arr = [{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}]
let obj = {}
arr.forEach(item => {
obj[item.Id] = item.qty
})
console.log(obj)
You can easily achieve this result using forEach in a single line of code.
const arr = [
{ Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 },
{ Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 },
];
const result = {};
arr.forEach(({ Id, qty }) => (result[Id] = qty));
console.log(result);
You can achieve the desired result with below code
//input array
const arrList = [
{Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1},
{Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1}
]
function findArray(arr) {
//define a new array to store Id's
let newArray = [];
//iterate through array items
arr.forEach(item => {
newArray.push(item.Id);
});
return newArray;
}
//call findArray function to get desired output
console.log(findArray(arrList));
Using Object.fromEntries()
const
array = [{ Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }, { Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }],
object = Object.fromEntries(array.map(({ Id, qty }) => [Id, qty]));
console.log(object);
or, for some fragile novelty...
const
array = [{ Id: "6d7e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }, { Id: "6d2e75e6-c58b-11e7-95-ac162d77eceb", qty: 1 }],
object = Object.fromEntries(array.map(Object.values));
console.log(object);

Transforming Javascript Array

I'm not sure what would be the best way to approach transforming this JS Array.
I have an array with a structure like (could contain more than 1 element):
let arr1 = [{amount: '10', quantity: 2, id: '123'}, {....}]
but I need to take that and transform that into an array structured like
let arr2 = [{value: '10'}, {value: '10'}]
Essentially adding new objects into the array based on the quantity in array 1.
I was thinking basic for loop but it seems to be getting a bit messy. Is there a simple way in JS to do this? Either with some sort of built in function etc?
You can easily get the result using flatMap.
First, you can create a temp array with the number of elements as quantity then map over the temp array to get the object with property amount in it.
let arr1 = [
{ amount: "10", quantity: 2, id: "123" },
{ amount: "30", quantity: 5, id: "123" },
];
const result = arr1.flatMap((obj) => {
const { amount, quantity } = obj;
return Array(quantity)
.fill(0)
.map((x) => ({ amount }));
});
console.log(result);
You can also make the above snippet succinct
const result = arr1.flatMap(({ quantity, amount }) => Array(quantity).fill(0).map((x) => ({ amount })));
let arr1 = [
{ amount: "10", quantity: 2, id: "123" },
{ amount: "30", quantity: 5, id: "123" },
];
const result = arr1.flatMap(({ quantity, amount }) =>
Array(quantity)
.fill(0)
.map((x) => ({ amount }))
);
console.log(result);
I was thinking basic for loop but it seems to be getting a bit messy
You just need a simple for and a while loop:
const input = [{amount: '10', quantity: 2, id: '123'}],
output = []
for (let { amount, quantity } of input)
while (quantity--)
output.push({ value: amount })
console.log(output)
You could create o.quantity number of objects using Array.from(). Use flatMap to get a flat array for each item in the input array
const output = input.flatMap(o =>
Array.from({ length: o.quantity }, _ => ({ value: o.amount }) )
)
You could also do it using reduce, with a manual for loop to append the correct number of entries.
let arr1 = [{amount: '10', quantity: 2, id: '123'}];
const result = arr1.reduce((accum, v) => {
for (let i = 0; i < v.quantity; i++) {
accum.push({value: v.amount});
}
return accum;
} , []);
This might have a slight performance improvement over flatMap, as it does not create any temporaries.

Filter array of objects but return only specific properties - JS [duplicate]

This question already has answers here:
Extract certain properties from all objects in array
(5 answers)
Closed 4 months ago.
How to filter an array of objects with a condition and return only specific properties of filtered objects?
I know we can use filter followed by map to achieve this. But I am looking for more simple solution.
For ex:
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}]
Suppose if I want only ids of name "lala".
Output should be,
[{id: 1}, {id: 3}]
The next simplest would be reduce
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}];
console.log(
arr.reduce((values, value) =>
{
if (value.name === 'lala') values.push({ id: value.id });
return values;
}, [])
);
You can simply use Array.prototype.reduce to combine both mapping and filtering in the same operation. If you want to make it super concise, you can use object destructuring in the second argument of the reduce callback:
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}];
let filteredMappedArr = arr.reduce((acc, { name, id }) => {
if (name === 'lala')
acc.push({ id });
return acc;
}, []);
console.log(filteredMappedArr);
filter followed by map is probably the most readable solution, but if you're looking to do it all in one step, you're looking at the classic for loop or using reduce.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
You can do it by using filter and map;
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}]
let res = arr.filter(item => item.id % 2 === 1).map(item => ({id: item.id}))
console.log(res);
You could take Array#flatMap and return either a new obejct or an empty array which has no value for flattening.
let array = [{ name: "lala", id: 1 }, { name: "coco", id: 2 }, { name: "lala", id: 3 }],
result = array.flatMap(({ id, name }) => name === 'lala' ? [{ id }] : []);
console.log(result);
using .filter() and .map() functions:
let arr = [{name:"lala", id: 1}, {name: "coco", id:2}, {name: "lala", id:3}]
let newArr = arr.filter((elm) => (elm.name === 'lala')).map( (elm) => {return {id:elm.id}});
console.log(newArr);
let arr = [
{ name: "lala", id: 1 },
{ name: "coco", id: 2 },
{ name: "lala", id: 3 },
];
let a = [];
arr.filter(({ name, id }) => {
if (name === "lala") {
a.push({ id });
}
});
console.log(a);
with filter we check for the condition where name matches 'lala' if yes then we push id to new array...that's simple

Filtering an array of objects from an array

I have an array of objects lookups and an array filters. Now I want to filter the array from an array of objects using the object attribute name.
I used filter and some but I could not get the expected result.
EXPECTED RESULT:
[{id: 3, name: "Linkedin"}]
let lookups = [
{id: 1, name: "Twitter"},
{id: 2, name: "Facebook"},
{id: 3, name: "Linkedin"}
]
let filters = ["Facebook", "Twitter"]
const filtered = lookups.filter(lookup => filters.some(filter => filter.toLowerCase() != lookup.name.toLowerCase()));
console.log(filtered)
Your code gives those elements in result for which some of the values in filters is not equal to element's name. So for each element some of the name is not equal.
In other words you are using != with || which will always return true.
let a = "anything";
console.log(a !== "thing1" || a !== "thing2")
You need to use every() instead of some().
let lookups = [
{id: 1, name: "Twitter"},
{id: 2, name: "Facebook"},
{id: 3, name: "Linkedin"}
]
let filters = ["Facebook", "Twitter"]
const filtered = lookups.filter(lookup => filters.every(filter => filter.toLowerCase() !== lookup.name.toLowerCase()));
console.log(filtered)

Compare object array with object and reduce quantity

I have an object containing an id as the key, and quantity as the value, e.g.;
let order = {1002: 2, 1010: 1}
I want to compare the order object with an array of products, e.g.:
let stock = [{name: "test", id: "1002", quantity: 100}, {name: "moreTest", id: "1010", quantity: 100}]
I want to reduce the quantity for each object in my stocks array, based on the according value in the stocks object, e.g.:
let newStock = [{name: "test", id: "1002", quantity: 98}, {name: "moreTest", id: "1010", quantity: 99}]
Here's a one-liner approach:
let newStock = stock.map(item => ({...item, quantity: item.quantity - (order[parseInt(item.id,10)] || 0)}))
BTW:
I think stock's id should be a number (or order needs to have a string key - I used parseInt but I don't think it's the best practice).
stock should be a map as well to prevent multiple stocks with the same id.
Here is a possible solution, very clear:
let order = {1002: 2, 1010: 1}
let stock = [{name: "test", id: "1002", quantity: 100}, {name: "moreTest", id: "1010", quantity: 100}]
stock.forEach(element => {
Object.keys(order).forEach(function(key) {
const quantityBought = order[key];
// == and not === because element.id is a string and key is a number
if (element.id == key) {
element.quantity -= quantityBought;
}
});
});
console.log(stock);
You can use Array.prototype.reduce here something Like this
let stock = [{name: "test", id: "1002", quantity: 100}, {name: "moreTest", id: "1010", quantity: 100}]
let order = {1002: 2, 1010: 1}
let result=stock.reduce((acc,value)=>{
value.quantity=value.quantity-order[value.id];
acc.push(value);
return acc;
},[])
console.log(result)
For reference look at array reduce function in mozilla docs

Categories