how to get array according to conditions in javascript - javascript

My array comes like this
var data=[{PRODUCT : P1}, {PRODUCT: P2}]
I wantt to convert this into [P1, P2].
Sometimes my array comes like this
var data=[{ITEM: I1, QUANTITY:1}, {ITEM: I2, QUANTITY:2}]
I wantt to convert this into [I1, I2].
so can we make a common function, where I just want to extract particular value of array and make a new array.
p.s. Thank you in advance
I tried to write the logic like this:
data.map((d, index) => { var result= [];
result.includes(d[0]); })
but it,s not dynamic

You could define a function which will always get the first value of the first object key, this should satisfy your needs based on the above
var data1 = [{
ITEM: 'I1',
QUANTITY: 1
}, {
ITEM: 'I2',
QUANTITY: 2
}]
var data2 = [{
PRODUCT: 'P1'
}, {
PRODUCT: ' P2'
}]
function getArrayOfValues(list) {
return list.reduce((acc, x) => {
const firstValue = Object.values(x)[0];
acc.push(firstValue)
return acc;
}, [])
}
const result1 = getArrayOfValues(data1)
console.log(result1)
const result2 = getArrayOfValues(data2)
console.log(result2)

function getProductOrItem(list) {
return list.reduce((accumulator, obj) => {
if (obj.PRODUCT) {
accumulator.push(obj.PRODUCT);
} else if (obj.ITEM) {
accumulator.push(obj.ITEM);
}
return accumulator;
}, [])
}

you can iterate through your array with map() method and inside it extract the value of a first entity of an object in your array and simply get a new array with all values:
const data1 =[{PRODUCT : 'P1'}, {PRODUCT: 'P2'}]
const data2 = [{ITEM: 'I1', QUANTITY: 1}, {ITEM: 'I2', QUANTITY: 2 }]
const transformValuesOfArray = (arrayToTransform) =>
arrayToTransform.map(value => {
const firstObjectValue = Object.values(value)[0]
return firstObjectValue
})
console.log(transformValuesOfArray(data1))
console.log(transformValuesOfArray(data2))

Related

How to create multiple objects from array of entries in JavaScript?

I receive an array of entries from form using FormData(). It consists of information about the recipe. Like this:
const dataArr = [
['title', 'pizza'],
['image', 'url'],
['quantity-0', '1'],
['unit-0', 'kg'],
['description-0', 'Flour'],
['quantity-1', '2'],
['unit-1', 'tbsp'],
['description-1', 'Olive oil'],
... // more ingredients
];
which I need to reorganize in new object, like this:
const recipe = {
title: 'pizza',
image: 'url',
ingredients: [
{ quantity: '1', unit: 'kg', ingredient: 'Flour' },
{ quantity: '2', unit: 'tbsp', ingredient: 'Olive oil' },
...
],
};
So, for ingredients array I need to create multiple objects from received data. I came up with needed result, but it's not clean. I would appreciate your help coming up with universal function, when number of ingredients is unknown.
My solution: Form receives 6 ingredients max, therefore:
const ingredients = [];
// 1. Create an array with length of 6 (index helps to get ingredient-related data looping over the array)
const arrayOf6 = new Array(6).fill({});
arrayOf6.forEach((_, i) => {
// 2. In each iteration filter over all data to get an array for each ingredient
const ingArr = dataArr.filter(entry => {
return entry[0].startsWith(`unit-${i}`) ||
entry[0].startsWith(`quantity-${i}`) ||
entry[0].startsWith(`ingredient-${i}`);
});
// 3. Loop over each ingredient array and rename future properties
ingArr.forEach(entry => {
[key, value] = entry;
if(key.includes('ingredient')) entry[0] = 'description';
if(key.includes('quantity')) entry[0] = 'quantity';
if(key.includes('unit')) entry[0] = 'unit';
});
// 4. Transform array to object and push into ingredients array
const ingObj = Object.fromEntries(ingArr);
ingredients.push(ingObj);
});
// To finalize new object
const dataObj = Object.fromEntries(dataArr);
const recipe = {
title: dataObj.title,
image: dataObj.image,
ingredients,
};
You'll have to parse the values of the input array to extract the index. To build the result object, you could use reduce:
const dataArr = [['title', 'pizza'],['image', 'url'],['quantity-0', '1'],['unit-0', 'kg'],['description-0', 'Flour'],['quantity-1', '2'],['unit-1', 'tbsp'], ['description-1', 'Olive oil']];
const recipe = dataArr.reduce((recipe, [name, value]) => {
const [, prop, index] = name.match(/^(\w+)-(\d+)$/) ?? [];
if (prop) {
(recipe.ingredients[index] ??= {})[prop] = value;
} else {
recipe[name] = value;
}
return recipe;
}, { ingredients: [] });
console.log(recipe);
You don't need arrayOf6. You never use its elements for anything -- it seems like you're just using it as a replacement for a loop like for (let i = 0; i < 6; i++).
Just loop over dataArr and check whether the name has a number at the end. If it does, use that as an index into the ingredients array, otherwise use the name as the property of the ingredients object. Then you don't need to hard-code a limit to the number of ingredients.
const dataArr = [
['title', 'pizza'],
['image', 'url'],
['quantity-0', '1'],
['unit-0', 'kg'],
['description-0', 'Flour'],
['quantity-1', '2'],
['unit-1', 'tbsp'],
['description-1', 'Olive oil'],
// more ingredients
];
const recipe = {
ingredients: []
};
dataArr.forEach(([name, value]) => {
let match = name.match(/^(\w+)-(\d+)$/);
if (match) {
let type = match[1];
let index = match[2];
if (!recipe.ingredients[index]) {
recipe.ingredients[index] = {};
}
recipe.ingredients[index][type] = value;
} else {
recipe[name] = value;
}
});
console.log(recipe);
Separating the key-parsing logic helps me think about the concerns more clearly:
const orderedKeyRegExp = /^(.+)-(\d+)$/;
function parseKey (key) {
const match = key.match(orderedKeyRegExp);
// Return -1 for the index if the key pattern isn't part of a numbered sequence
if (!match) return {index: -1, name: key};
return {
index: Number(match[2]),
name: match[1],
};
}
function transformRecipeEntries (entries) {
const result = {};
const ingredients = [];
for (const [key, value] of entries) {
const {index, name} = parseKey(key);
if (index >= 0) (ingredients[index] ??= {})[name] = value;
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// Assign an empty object to the element of the array at the index
// (if it doesn't already exist)
else result[name] = value;
}
if (ingredients.length > 0) result.ingredients = ingredients;
return result;
}
const entries = [
['title', 'pizza'],
['image', 'url'],
['quantity-0', '1'],
['unit-0', 'kg'],
['description-0', 'Flour'],
['quantity-1', '2'],
['unit-1', 'tbsp'],
['description-1', 'Olive oil'],
// ...more ingredients
];
const result = transformRecipeEntries(entries);
console.log(result);

Loop into array object then check if there's a equal value?

Question, I have this array object, I want to find out which of this array have a similar values
then make them as one.
Example
[0:
cartProduct: {
category: "chair"
color: "navy"
id: "628a1738fd8299ae6659d994"
image: "http://localhost:5000/../public/Product_chair_communal-navy.jpg"
name: "The Communal"
price: "4.30"
}
quantity: 1,
1:
cartProduct: {{
category: "chair"
color: "navy"
id: "628a1738fd8299ae6659d994"
image: "http://localhost:5000/../public/Product_chair_communal-navy.jpg"
name: "The Communal"
price: "4.30"
}
quantity: 1,
]
For example the data above I want to know if they have the similar values interms of color if yes then only return one value.
Thanks!
You can use this loop:
let uniqueArray = [];
dataArray.forEach((item, indx) => {
let colorsArray = [];
if (colorsArray.includes(item.color)) {
continue;
}
uniqueArray.push(item);
})
Not the cleanest, or most performant approach:
// function to group the items
const groupCartItems = (items, byProperties = ['color', 'id']) => {
// utility funciton
const verifyEquality = (itemA, itemB) => {
let isEqual = true;
byProperties.forEach((prop) => {
if (itemA.cartProduct[prop] != itemB.cartProduct[prop]) {
isEqual = false;
break;
}
});
return isEqual;
};
const groupedItems = [];
items.forEach((item) => {
// if item has been added, skip
if (groupedItems.find((i) => verifyEquality(item, i))) {
return;
}
// find equal items
const equals = items.filter((i) => verifyEquality(item, i));
// sum quantities
const quantity = equals.reduce((previousValue, data) => previousValue + data.quantity, 0);
// push
groupedItems.push({
cartProduct: item.cartProduct,
quantity,
});
});
return groupedItems;
};
For the 'similarity' stuff, I would recommend not to do this, because it is just not a good practise. Have your values equal or else!!!
Now seriously, check string-similarity. From documentation, you would only need to change the if inside verifyEquality function to:
import stringSimilarity from 'string-similarity';
// tweak this value to change how similar strings should be to be considered equal
const EQUALITY_RATIO = 0.75;
// ....
if (stringSimilarity.compareTwoStrings(itemA.cartProduct[prop], itemB.cartProduct[prop]) < EQUALITY_RATIO) {
}

Extract data from object based on key in JavaScript

I am trying to find the property value of an object based on key. I have below function getData which returns the data based on key passed as input parameter.
const getData = (key) => {
let row = {isSelected: true, Data: {Id: '1A', Value: 'LD'}};
return row[key];
}
console.log(getData('Data'));
In normal scenario it is working fine but how can I get the property value from nested object Data.Value.
If I call getData function as getData('Data.Value'), It should return LD.
You can use lodash's _.get() function that returns the value at a path:
const getData = path => {
const row = {isSelected: true, Data: {Id: '1A', Value: 'LD', InnerData: {Id: 1, Value: "Something"}}};
return _.get(row, path);
}
console.log(getData('Data'));
console.log(getData('Data.Value'));
console.log(getData('Data.InnerData.Value'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
I would suggest accessing the nested value like this:
getData("Data").Value
This is what you want. It is not matter how deep is your row. Try this. It would be multilevel nested object too. For example
Data.InnerData.Value...
const getData = (key) =>{
let row = {isSelected: true, Data: {Id: '1A', Value: 'LD', InnerData: {Id: 1, Value: "Something"}}};
var keys = key.split('.');
var res = row;
for(var i=0; i < keys.length; i++){
res = res[keys[i]];
}
return res;
}
console.log(getData('Data.InnerData.Value'));
When you have dynamic object keys you can use javascript Object.keys method.
var data = getData("Data")
var dynamicKeys = Object.keys(data)
for(int i=0; i < dynamicKeys.length; i++){
console.log(data[dynamicKeys[i]])
}
If you are certain that your object goes two level at most, you can try this simple solution
const isObject = (value) => {
return typeof value === 'object' && !Array.isArray(value) && value !== null;
};
const testData = { isSelected: true, data: { id: '1A', value: 'LD' } };
const getData = (key) => {
const keys = key.split('.');
if (isObject(testData[keys[0]])) {
return testData[keys[0]][keys[1]];
}
return testData[keys[0]];
};
console.log(getData('data.id'));

How to dynamically add data from an array with objects to a nested array?

I have this set of data that I get dynamically -
This is the data I dynamically get
and my question is how can I get the values from the key, pattern and label and put them in a nested object like this - how should the nested object look like.
My current code is
let mergeTagsObj = {};
const merg = function(arr){
const propertyDataMap = arr.map(x => x.key);
propertyDataMap.forEach(x => {
mergeTagsObj[x] = {}
});
console.log(mergeTagsObj);
// console.log(object);
};
merg(displayArr)
displayArr has the data that I dynamically get, and I map each one to get the key so I can then give the object property a name. But after that I need to get the other 2 (pattern and label) and put it in the mergeTagsObj;
ex: mergeTagsObj = {
firstName:{
name:{label}
value:{pattern}
},
...
};
You can add the pattern and label in your forEach and any other logic that you might need to transform the data.
const data = [{key: 'firstName', pattern: "{{firstName}}", label: "First Name"},
{key: 'lastName', pattern: "{{lastName}}", label: "Last Name"},
{key: 'unsubscribeLink', pattern: "{{unsubscribeLink}}", label: "Unsubscribe Link"}
]
const transformDataToTagsObject = (dData) => {
const dynamicData = {};
dData.forEach((currentData, index) => {
const currentKey = currentData.key
const name = currentData.label
let value = currentData.pattern
if(currentData.key === 'unsubscribeLink'){
value = `<a href='${value}'>Unsubscribe</a>`
}
dynamicData[currentKey] = {
name,
value
}
})
const tagsObject = {
tags: dynamicData
}
return tagsObject;
}
const finalResults = transformDataToTagsObject(data)
console.log(finalResults)
Not most elegant solution, but I think this should work. Don't need to create the array of keys first you can just iterate over the arr of objects.
const merg = function(arr){
arr.forEach(x => {
mergeTagsObj[x.key] = {};
mergeTagsObj[x.key]['name'] = x.label;
mergeTagsObj[x.key]['value'] = x.pattern
});
console.log(mergeTagsObj);
// console.log(object);
};
// Given
const data = [
{key: "firstName", pattern: "{{firstName}}", label: "First Name"},
{key: "unsubscribeLink", pattern: "{{unsubscribeLink}}", label: "Unsubscribe Link"}
];
const tagsObject = data.reduce((obj, item) => {
const key = item.key;
const name = item.label;
let value = item.pattern;
if (key === 'unsubscribeLink') value = 'Unsubscribe';
return {...obj, [key]: {name, value}};
}, {});
console.log(tagsObject);

flatten array of object into an array

const x = [{
name:"abc",
},{
name:"xyz"
}]
how to turn above array of object into an array?
expected output
x = ['abc','xyz']
I know I can do a native loop, use push to a new empty array but I'm looking for one line es2015/es6 or even lodash method
Simply use the map function:
const y = x.map(c => c.name);
const x = [{
name:"abc",
},{
name:"xyz"
}]
const names = x.map(c => c.name);
console.log(names);
Solution in Lodash (very similar to plain js):
const x = [{
name:"abc",
},{
name:"xyz"
}]
const names _.map(x, 'name'); // => ['abc', 'xyz']
Edit
as requested also in plain js
const names = x.map(el => el.name);
or
const names = x.map(function(el) {
return el.name;
});
x = [{
name:"abc",
},{
name:"xyz"
}];
x = x.map(function (value) {
return value.name;
});
Use map()
let res = x.map(o => o.name);

Categories

Resources