Converting an array of array to a single array of object - javascript

I have a data structure that looks like this:
let a = [
["base-certificate", 60, 3, 2022],
["case-certificate", 1, 3, 2022],
["standard-certificate", 7, 3, 2022],
];
I want to transform it to look like this:
[{x:[3, 2022], base: 60, case:1, standard: 7}]
I tried using the map method on the array like:
let a = [
["base-certificate", 60, 3, 2022],
["case-certificate", 1, 3, 2022],
["standard-certificate", 7, 3, 2022],
];
let result = a.map((elem) => {
let obj = {};
elem.forEach((e, i) => {
obj["x"] = [e[2], e[3]];
obj[e[0]] = e[1];
});
return obj;
});
console.log(result);
The code above did not get the desired output.
what is the best way to go about this?

You don't need both the map and the forEach, you can remove the outer map.
Also if you want to remove the "-certificate" part, you can use a split.
Something like this should work
let a = [
["base-certificate", 60, 3, 2022],
["case-certificate", 1, 3, 2022],
["standard-certificate", 7, 3, 2022],
];
let obj = {};
a.forEach((e, i) => {
obj["x"] = [e[2], e[3]];
obj[e[0].split('-')[0]] = e[1];
});
console.log(obj);

map() is for creating an array. You just want one object, you should declare it outside the loop and use forEach() to fill it in. You don't need nested loops.
You can use replace() to remove -certificate from the names.
let a = [
["base-certificate", 60, 3, 2022],
["case-certificate", 1, 3, 2022],
["standard-certificate", 7, 3, 2022],
];
let obj = {};
a.forEach((e, i) => {
obj["x"] = [e[2], e[3]];
obj[e[0].replace('-certificate', '')] = e[1];
});
console.log(obj);

let a = [
["base-certificate", 60, 3, 2022],
["case-certificate", 1, 3, 2022],
["standard-certificate", 7, 3, 2022],
];
let obj = {};
a.forEach((e) => {
obj["x"] = [e[2], e[3]];
obj[e[0].replace('-certificate',"")] = e[1];
});
console.log([obj]);

Related

How do I multiply an array of numbers with another array of numbers in javascript

I've been trying to make an array of numbers be able to times another array of numbers without doing array.join("") * array2.join("").
I've tried a lot of methods such as:
var input = [3, 6, 4];
var scalar = 5;
var output = input.map(x => x * scalar); // [15, 30, 20]
Although that's only one number the array can multiply to.
I'd like a function that can do:
var array = [ 1, 3, 2 ];
var array2 = [ 5, 3, 8, 2, 3, 5, 2 ];
someFunction(array, array2);
// [ 7, 1, 0, 4, 7, 0, 4, 6, 4 ]
Please note I don't want it to be something like
array.join("") * array2.join("")
I'm willing to give all my reputation as a bounty if someone is able to answer my question.
If scientific notation is the problem, turn the arrays into BigInts instead.
var array = [ 1, 3, 2, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5 ];
var array2 = [ 5, 3, 8, 2, 3, 5, 2, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5 ];
const someFunction = (arr1, arr2) => [...String(
BigInt(arr1.join('')) * BigInt(arr2.join(''))
)].map(Number);
console.log(someFunction(array, array2));

How to replace duplicate objects from array

I know there are multiple ways to remove duplicates from arrays in javascript, the one i use is
let originalArray = [1, 2, 3, 4, 1, 2, 3, 4]
let uniqueArray = array => [...new Set(array)]
console.log(uniqueArray) -> [1, 2, 3, 4]
what i want is something similar but instead of removing the duplicates, to replace it with whatever string or number i want, like this
console.log(uniqueArray) -> [1, 2, 3, 4, "-", "-", "-", "-"]
this has to work with any order, like
[1, 2, 3, 3, 4, 5, 7, 1, 6]
result -> [1, 2, 3, "-", 4, 5, 7, "-", 6]
i tested this solution
const arr = [1, 2, 3, 1, 2, 3, 2, 2, 3, 4, 5, 5, 12, 1, 23, 4, 1];
const deleteAndInsert = uniqueList => {
const creds = uniqueList.reduce((acc, val, ind, array) => {
let { count, res } = acc;
if (array.lastIndexOf(val) === ind) {
res.push(val);
} else {
count++;
};
return { res, count };
}, { count: 0, res: [] });
const { res, count } = creds;
return res.concat(" ".repeat(count).split(" "));
};
console.log(deleteAndInsert(arr));
but only adds it at the end of the uniques, and also, only works with numbers
i want it to work with strings too, like dates as an example
["2021-02-22", "2021-02-23", "2021-02-22", "2021-02-28"]
You could still use a Set and check if the value is in the set.
const
unique = array => array.map((s => v => !s.has(v) && s.add(v) ? v : '-')(new Set));
console.log(...unique([1, 2, 3, 4, 1, 2, 3, 4]));
console.log(...unique([1, 2, 3, 3, 4, 5, 7, 1, 6]));
Just create new Array, use 1 set to control which element appeared, if one element appears more than 1, push new one character like '-'
let originalArray = [1, 2, 3, 4, 1, 2, 3, 4];
let newArray = [];
let set = new Set();
for (let i = 0; i < originalArray.length; i++) {
if(!set.has(originalArray[i])) {
newArray.push(originalArray[i]);
set.add(originalArray[i]);
} else {
newArray.push('-');
}
}
console.log(newArray);
You could do it with reduce
const dashDupes = array => array.reduce((acc, e) => {
if(acc.idx[e])
acc.arr.push('-')
else{
acc.arr.push(e);
}
acc.idx[e] = true;
return acc;
},{idx:{},arr:[]}).arr
console.log(...dashDupes([1, 2, 3, 4, 1, 2, 3, 4]))
console.log(...dashDupes([1, 2, 3, 3, 4, 5, 7, 1, 6]))
This is a very simple approach to the problem:
function uniqueReplace(arr, rep) {
let res = [];
for (x of arr) {
res.push(res.includes(x) ? rep : x);
}
return res;
}
console.log(...uniqueReplace([1, 2, 3, 4, 1, 2, 3, 4], '-'));
console.log(...uniqueReplace([1, 2, 3, 3, 4, 5, 7, 1, 6], '-'));

Clone a object JSON but until its 5th key-value

I have a JSON that has more than 10 key-values, I need to create a copy of this but limiting it until the 5th key-value.
Input:
var object1 = {
"1a": 1,
"2b": 2,
"3c": 1,
"4d": 2,
"5e": 1,
"6f": 2,
"7g": 1,
"8h": 2,
"9i": 1,
"10j": 2
};
Desired output:
var object2 = {
"1a": 1,
"2b": 2,
"3c": 1,
"4d": 2,
"5e": 1,
};
I'm thinking about creating a new one key per key by using a for until 10th. Any thoughts?
You could slice the array of entries and rebuild a new object with Object.fromEntries.
var object = { "1a": 1, "2b": 2, "3c": 1, "4d": 2, "5e": 1, "6f": 2, "7g": 1, "8h": 2, "9i": 1, "10j": 2 },
result = Object.fromEntries(Object.entries(object).slice(0, 5));
console.log(result);
The same with Object.assign.
var object = { "1a": 1, "2b": 2, "3c": 1, "4d": 2, "5e": 1, "6f": 2, "7g": 1, "8h": 2, "9i": 1, "10j": 2 },
result = Object.assign({}, ...Object
.entries(object)
.slice(0, 5)
.map(([k, v]) => ({ [k]: v }))
);
console.log(result);
You could easily use something like this, it's a relatively standard implementation by making use of the reduce method.
What's good about this solution is that it's so simple that even beginners can make sense of it.
var object1 = {
"1a": 1,
"2b": 2,
"3c": 1,
"4d": 2,
"5e": 1,
"6f": 2,
"7g": 1,
"8h": 2,
"9i": 1,
"10j": 2
};
var object2 = Object.keys(object1).reduce((o, k, i) => {
i < 5 ? o[k] = object1[k] : null;
return o;
}, {});
console.log(object2);

Remove all of the duplicate numbers in an array of numbers [duplicate]

This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 3 years ago.
I received this question for practice and the wording confused me, as I see 2 results that it might want.
And either way, I'd like to see both solutions.
For example, if I have an array:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
I'm taking this as wanting the final result as either:
let finalResult = [1, 2, 3, 4, 5, 8, 9, 10];
OR:
let finalResult = [1, 9, 10];
The difference between the two being, one just removes any duplicate numbers and leaves the rest and the second just wants any number that isn't a duplicate.
Either way, I'd like to write two functions that does one of each.
This, given by someone else gives my second solution.
let elems = {},
arr2 = arr.filter(function (e) {
if (elems[e] === undefined) {
elems[e] = true;
return true;
}
return false;
});
console.log(arr2);
I'm not sure about a function for the first one (remove all duplicates).
Using Set and Array.from()
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
console.log(Array.from(new Set(arr)));
Alternate using regex
regex explanation here
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let res = arr
.join(',')
.replace(/(\b,\w+\b)(?=.*\1)/ig, '')
.split(',')
.map(Number);
console.log(res);
Alternate using objects
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let obj = arr.reduce((acc, val) => Object.assign(acc, {
[val]: val
}), {});
console.log(Object.values(obj));
Just use a simple array.filter one-liner:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let finalResult = arr.filter((e, i, a) => a.indexOf(e) == i).sort(function(a, b){return a - b});
console.log(finalResult);
You could use another filter statement if you wanted the second result:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let finalResult = arr.filter((e, i, a) => a.filter(f => f == e).length == 1).sort(function(a, b){return a - b});
console.log(finalResult);
For the first part you can use Set() and Spread Syntax to remove duplicates.
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let res = [...new Set(arr)]
console.log(res)
For the second part you can use reduce()
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
//to get the object with count of each number in array.
let obj = arr.reduce((ac,a) => {
//check if number doesnot occur before then set its count to 1
if(!ac[a]) ac[a] = 1;
//if number is already in object increase its count
else ac[a]++;
return ac;
},{})
//Using reduce on all the keys of object means all numbers.
let res = Object.keys(obj).reduce((ac,a) => {
//check if count of current number 'a' is `1` in the above object then add it into array
if(obj[a] === 1) ac.push(+a)
return ac;
},[])
console.log(res)
You can use closure and Map
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const build = ar => {
const mapObj = ar.reduce((acc, e) => {
acc.has(e) ? acc.set(e, true) : acc.set(e, false)
return acc
}, new Map())
return function(hasDup = true) {
if(hasDup) return [...mapObj.keys()]
else return [...mapObj].filter(([key, val]) => !val).map(([k, v])=> k)
}
}
const getArr = build(arr)
console.log(getArr())
console.log(getArr(false))
You can create both arrays in One Go
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let unique = new Set();
let repeated = Array.from(arr.reduce((acc, curr) => {
acc.has(curr) ? unique.delete(curr) : acc.add(curr) && unique.add(curr);
return acc;
}, new Set()));
console.log(Array.from(unique))
console.log(repeated)
You can use Array.prototype.reduce() create a hash object where the keys are the numbers in the array and the values are going to be the the repeated occurrence of numbers in the arr array variable..
Then using Object.keys():
Remove all duplicates Object.keys(hash)
Remove all duplicates but filtering with Array.prototype.filter() to get the numbers with only one occurrence
Code:
const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const hash = arr.reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), {});
// [1, 2, 3, 4, 5, 8, 9, 10];
const finalResultOne = Object.keys(hash);
// [1, 9, 10];
const finalResultTwo = Object.keys(hash).filter(k => hash[k] === 1);
console.log('finalResultOne:', ...finalResultOne);
console.log('finalResultTwo:', ...finalResultTwo);
You could sort the array before and filter the array by checking only one side for duplicates or both sides.
var array = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10],
result1,
result2;
array.sort((a, b) => a - b);
result1 = array.filter((v, i, a) => a[i - 1] !== v);
result2 = array.filter((v, i, a) => a[i - 1] !== v && a[i + 1] !== v);
console.log(...result1);
console.log(...result2)
As many other have said, the first one is just [...new Set(arr)]
For the second, just filter out those that occur more than once:
const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const count = (arr, e) => arr.filter(n => n == e).length
const unique = arr => arr.filter(e => count(arr, e) < 2)
console.log(unique(arr));
var arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
var map = {};
var finalResult = [];
for (var i = 0; i < arr.length; i++) {
if (!map.hasOwnProperty(arr[i])) {
map[arr[i]] = true;
finalResult.push(arr[i]);
}
}
//if you need it sorted otherwise it will be in order
finalResult.sort(function(a, b) {
return a - b
});
console.log(finalResult);

Populating array from a repeating array

I'm making a small tool for handling translations for a website. I already got this code working, but I feel there should be some more elegant and readable way using array methods (mine looks like a mess...).
Basically, I'll get input in the format shown in code (data_import, this is just fake data for testing). It has 4 columns [translationTag, uniqueId, languageId, translation]. Order of rows is same for every language and there is same number of rows for each language. Number of languages may change from 2 upwards.
the desired output would be like this:
const data_import = [
['aaa', {id:1, langId:1, finnish:'tuntematon'}, {id:5, langId:4, english:'unknown'}, {id:9, langId:6, swedish:'okänd'}],
['bbb', {id:2, langId:1, finnish:'auto'}, {id:6, langId:4, english:'car'}, {id:10, langId:6, swedish:'bil'}],
['ccc', {id:3, langId:1, finnish:'polkupyörä'}, {id:7, langId:4, english:'bicycle'}, {id:11, langId:6, swedish:'cykel'}],
['ddd', {id:4, langId:1, finnish:'rullalauta'}, , {id:8, langId:4, english:'skateboard'}, {id:12, langId:6, swedish:'skateboard'}]
];
Here is my code that 'works' but is ugly and unreadable...
export const language = ['Finnish', 'Estonia', 'Polish', 'English', 'Spanish', 'Swedish'];
const data_import = [
['aaa', 1, 1, 'tuntematon'],
['bbb', 2, 1, 'auto'],
['ccc', 3, 1, 'polkupyörä'],
['ddd', 4, 1, 'rullalauta'],
['aaa', 5, 4, 'unknown'],
['bbb', 6, 4, 'car'],
['ccc', 7, 4, 'bicycle'],
['ddd', 8, 4, 'skateboard'],
['aaa', 9, 6, 'okänd'],
['bbb', 10, 6, 'bil'],
['ccc', 11, 6, 'cykel'],
['ddd', 12, 6, 'skateboard']];
export const data = process_test(data_import);
function process_test(data) {
const numberOfCols = data[0].length;
const idIndex = numberOfCols - 2;
const arr_result = []
let rowMax = 0;
let rowMaxMulti = 0;
let langIdLast = 0;
data.forEach((row, index) => {
// if = add non-language cols and first language column
if(row[idIndex] === data[0][idIndex]) {
rowMax = index + 1;
const transItem = row.slice(0, idIndex-1);
transItem.push({ id:row[idIndex], langId:row[idIndex], [language[row[idIndex] - 1]]:row[idIndex + 1] });
arr_result[index] = transItem;
langIdLast = row[idIndex];
}
// add other languages to datarow
else {
const transItem = { id:row[idIndex - 1], langId:row[idIndex], [language[row[idIndex] + 1]]:row[idIndex + 1] };
if(langIdLast !== row[idIndex]) rowMaxMulti++;
arr_result[index - rowMax * rowMaxMulti].push(transItem);
langIdLast = row[idIndex];
}
})
return(arr_result);
}
It would be simpler to reduce into an object indexed by the translation tag, and then get that object's values. On each iteration, create an array for the translation tag if it doesn't already exist in the accumulator. Identify the language name from the langId of the current item, and push the new object to the array:
const language = ['Finnish', 'Estonia', 'Polish', 'English', 'Spanish', 'Swedish'];
const data_import = [
['aaa', 1, 1, 'tuntematon'],
['bbb', 2, 1, 'auto'],
['ccc', 3, 1, 'polkupyörä'],
['ddd', 4, 1, 'rullalauta'],
['aaa', 5, 4, 'unknown'],
['bbb', 6, 4, 'car'],
['ccc', 7, 4, 'bicycle'],
['ddd', 8, 4, 'skateboard'],
['aaa', 9, 6, 'okänd'],
['bbb', 10, 6, 'bil'],
['ccc', 11, 6, 'cykel'],
['ddd', 12, 6, 'skateboard']];
const data = Object.values(data_import.reduce((a, [tTag, id, langId, word]) => {
if (!a[tTag]) a[tTag] = [tTag];
const langName = language[langId - 1];
a[tTag].push({ id, langId, [langName]: word });
return a;
}, {}));
console.log(data);
You can group the data by tag with Array.prototype.reduce and map it out to the desired format with Object.keys
const language = ['Finnish', 'Estonia', 'Polish', 'English', 'Spanish', 'Swedish'];
const data_import = [['aaa', 1, 1, 'tuntematon'],['bbb', 2, 1, 'auto'],['ccc', 3, 1, 'polkupyörä'],['ddd', 4, 1, 'rullalauta'],['aaa', 5, 4, 'unknown'],['bbb', 6, 4, 'car'],['ccc', 7, 4, 'bicycle'],['ddd', 8, 4, 'skateboard'],['aaa', 9, 6, 'okänd'],['bbb', 10, 6, 'bil'],['ccc', 11, 6, 'cykel'],['ddd', 12, 6, 'skateboard']];
const grouped = data_import.reduce((all, [tag, id, langId, tran]) => {
if (!all.hasOwnProperty(tag)) all[tag] = [];
all[tag].push({id, langId, [language[langId-1]]: tran});
return all;
}, {});
const result = Object.keys(grouped).map(tag => [tag, ...grouped[tag]]);
console.log(result);
You could also use
Array.prototype.map()
Array.prototype.filter()
new Set([])
destructuring assignment
const data_import = [["aaa",1,1,"tuntematon"],["aaa",5,4,"unknown"],["aaa",9,6,"okänd"],["bbb",6,4,"car"],["bbb",2,1,"auto"],["bbb",10,6,"bil"],["ccc",11,6,"cykel"],["ccc",7,4,"bicycle"],["ccc",3,1,"polkupyörä"],["ddd",8,4,"skateboard"],["ddd",4,1,"rullalauta"],["ddd",12,6,"skateboard"]],
language = ['Finnish', 'Estonia', 'Polish', 'English', 'Spanish', 'Swedish'];
const keys =[...new Set(data_import.map(v => v[0]))];
let result = keys.map(key => [key, data_import.filter(v => v[0] == key).map(v => {
return {
id: v[1],
langId: v[2],
[language[v[2]-1]]: v[3]
}
})]);
console.log(result)
.as-console-wrapper {max-height: 100% !important;top: 0;}

Categories

Resources