Convert string array into object with same key/value - javascript

How do I convert ["one","two","three"] into {one:"one", two:"two", three:"three"}
import stringArray from './a.js';
class b {
hashmap = stringArray// convert this into Object here inline.
}
Before you jump I know of for how to achieve this in say constructor() with tricks like forEach, for in loop etc. Is there a simple one line code to achieve this in the class property not inside a function.

Lodash
You can use _.zipObject. It accepts two arrays - one for keys, another for values but if you just use the same array twice you'd get matching pairs:
const arr = ["one","two","three"];
const obj = _.zipObject(arr, arr);
console.log(obj);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
Plain JavaScript
You can use Object.fromEntries to do the same thing. It works with an array of key-value pairs, so you'll have to transform yours to that:
const arr = ["one","two","three"];
const matchingKeyValuePairs = arr.map(x => [x, x]);
const obj = Object.fromEntries(matchingKeyValuePairs);
console.log(obj);
Also you can use Array#reduce to generate an object with a computed property name:
const arr = ["one","two","three"];
const obj = arr.reduce((acc, item) => ({...acc, [item]: item}), {});
console.log(obj);

data = ["one","two","three"];
data = data.map(e => [e,e]) // keyvalue pairs [["one","one"],["two","two"],["three","three"]]
data = Object.fromEntries(data); // {"one":"one","two":"two","three":"three"}
map will convert each element of your input array to a structure you want.
In this case, we want to convert each element to an array with the element repeated twice in it
Object.froEntries will convert a list of key-value pair to an Object
This can be also done with the plain old for loop
data = ["one","two","three"];
obj = {};
for(let i = 0; i < data.length ; i++){
obj[data[i]] = data[i];
}

Try this:
const arr = ["one","two","three"]
let obj = {}
arr.forEach(item => {obj[item] = item})
document.write(JSON.stringify(obj))

Lodash has the _.keyBy() function, that creates an object from an array by generating keys from the values via the function supplied (the iteratee). The default iteratee is _.identity(), which returns the value.
const arr = ["one","two","three"];
const obj = _.keyBy(arr);
console.log(obj);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>

Related

Make an array A with the result of each value of array B splitted by pipe

I have an array of strings. Some of the strings within this array have a pipe character. I would like to split the strings by "|" and store all the unique values into a new array.
What would be an efficient way to get a temporary array with all the splited values in it, without using poor performance loops?
Once I have the temporary array with all the splited values in it, I plan de remove all duplicates like this :
var result = [...new Set(result)]
var arr = ["A|B|C","B|A","E|A|D","F"]
// result does not have to be sorted
var expectedResult = ["A","B","C","D","E","F"]
Use flatMap() and split() to get a single array, and use a Set to retain unique elements:
const array = ["A|B|C","B|A","E|A|D","F"];
const result = [...new Set(array.flatMap(v => v.split('|')))];
console.log(result);
.join('|') array as a string with pipes between all letters, then .split('|') by the pipe and then remove dupes with Set()
let data = ["A|B|C", "B|A", "E|A|D", "F"];
console.log([...new Set(data.join('|').split('|'))]);
I would go with
const result = arr.map(item => item.split("|")).flat();
const deduped = [...new Set(result)]
One more option:
const inputArray = ["A|B|C","B|A","E|A|D","F"];
const result = inputArray.reduce((acc, value) => acc.push(...value.split('|')) && acc, []);
console.log(result);
const splitSet = (arr) => {
const set = new Set();
for(const item of arr) {
const splited = item.split("|");
for(const piece of splited) {
set.add(piece);
}
}
return Array.from(set);
}
splitSet(arr); //result
The first thing that comes to my mind is this
const arr = ["A|B|C","B|A","E|A|D","F"];
const flatArr = arr.join('|').split('|');
const expectedResult = [...new Set(flatArr)];

How i can to convert array to object of array in react?

I have a data in array
["Avengers","Batman","Spiderman","IronMan"]
how I can to covert to below
{"Avenger":"Avenger","Batmane":"Batman","Spiderman":"Spiderman","Ironman":"Ironman"}
You can do it like this:
let arr = ["Avengers","Batman","Spiderman","IronMan"];
let obj = arr.reduce((acc, item)=> ({...acc, [item]: item}) , {});
console.log(obj);
Someone else mentioned reduce, but I recommend against, copying objects at every iteration.
Here's a more performant approach.
const arr = ["Avengers","Batman","Spiderman","IronMan"];
const obj = {};
for (const el of arr) {
obj[el] = el;
}
console.log(obj);
You can use reduce to convert array to object.
You can see some examples in here Convert Array to Object

Find Unique value from an array based on the array's string value (Javascript)

so I want to find unique values from an array.
so for example I have this array:
const mainArr = ['shape-10983', 'size-2364', 'size-7800', 'size-4602', 'shape-11073', 'size-15027', 'size-15030', 'size-15033', 'height-3399', 'height-5884']
so I want to find the first matching value for each unique item.
for example, in the array, I have two strings with the shape prefix, six items with the size prefix, and two items with the height prefix.
so I want to output to be something like
const requiredVal = ["shape-10983", "size-2364", "height-3399"]
I want only the first value from any set of different values.
the simplest solution will be to iterate on the list and storing what you got in a dictionary
function removeSimilars(input) {
let values = {};
for (let value of input) {//iterate on the array
let key = value.splitOnLast('-')[0];//get the prefix
if (!(key in values))//if we haven't encounter the prefix yet
values[key] = value;//store that the first encounter with the prefix is with 'value'
}
return Object.values(values);//return all the values of the map 'values'
}
a shorter version will be this:
function removeSimilars(input) {
let values = {};
for (let value of input)
values[value.splitOnLast('-')[0]] ??= value;
return Object.values(values);
}
You could split the string and get the type and use it aks key for an object along with the original string as value. At result take only the values from the object.
const
data = ['shape-10983', 'size-2364', 'size-7800', 'size-4602', 'shape-11073', 'size-15027', 'size-15030', 'size-15033', 'height-3399', 'height-5884'],
result = Object.values(data.reduce((r, s) => {
const [type] = s.split('-', 1);
r[type] ??= s;
return r;
}, {}));
console.log(result);
If, as you mentioned in the comments, you have the list of prefixes already available, then all you have to do is iterate over those, to find each first element that starts with that prefix in your full list of possible values:
const prefixes = ['shape', 'size', 'height'];
const list = ['shape-10983', 'size-2364', 'size-7800', 'size-4602', 'shape-11073', 'size-15027', 'size-15030', 'size-15033', 'height-3399', 'height-5884']
function reduceTheOptions(list = [], prefixes = [], uniques = []) {
prefixes.forEach(prefix =>
uniques.push(
list.find(e => e.startsWith(prefix))
)
);
return uniques;
}
console.log(reduceTheOptions(list, prefixes));
Try this:
function getRandomSet(arr, ...prefix)
{
// the final values are load into the array result variable
result = [];
const randomItem = (array) => array[Math.floor(Math.random() * array.length)];
prefix.forEach((pre) => {
result.push(randomItem(arr.filter((par) => String(par).startsWith(pre))));
});
return result;
}
const mainArr = ['shape-10983', 'size-2364', 'size-7800', 'size-4602', 'shape-11073', 'size-15027', 'size-15030', 'size-15033', 'height-3399', 'height-5884'];
console.log("Random values: ", getRandomSet(mainArr, "shape", "size", "height"));
I modified the #ofek 's answer a bit. cuz for some reason the ??= is not working in react project.
function removeSimilars(input) {
let values = {};
for (let value of input)
if (!values[value.split("-")[0]]) {
values[value.split("-")[0]] = value;
}
return Object.values(values);
}
create a new array and loop over the first array and check the existing of element before in each iteration if not push it to the new array

Filter object in javascript

I am trying to filter through an array of objects and delete one of the object but keep the rest inside an array of objects but i keep returning either an array of arrays or i create nested objects. Is it possible to send in an array of objects and return and array of objects without that specific object? Below is the code I have been trying to work with.
function deleteWorkout(workoutName) {
const updatedArray = myWorkoutToDisplay.map((item) => item.newWorkToAdd.filter((workout) => workout.name !== workoutName))
const objectArray = [{updatedArray}]
const newWorkToAdd = objectArray.filter(e => e.length)
const workouts = [{newWorkToAdd}]
setMyWorkoutToDisplay(updatedArray)
}
You can easily do this with Array.prototype.filter. I guess the easiest way to delete 1 object is like this:
//let arr = arrayLike
//let objToDelete = whatever you want to delete
let newArr = arr.filter(obj => obj !== objToDelete)
newArr now has the array, without the deleted item. arr however still has it. To delete item by index, use this:
//let arr = arrayLike
//let ind = index to delete
let newArr = arr.filter((_, index) => index !== ind)

Convert JSON to Array of Objects using lodash

I have a JSON object in NoSql database in this format. We are getting this data after migrating some records from some other database and these are multi-valued fields.(Basically we are trying to clean the data for further processing).
{
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
}
I want to add another key "bpTableDataName" in the same JSON which should have this format and values,
"bpTableDataName": [
{
"name": "aName",
"email": "aEmail",
"pwdid": "aPWID"
},
{
"name": "bName",
"email": "bEmail",
"pwdid": "bPWID"
},
{
"name": "cName",
"email": "cEmail",
"pwdid": "cPWID"
}
],
Is there a way we can achieve this using lodash?
Try following code -
o = {
"BPContName": "aName;bName;cName",
"BPContEmail": "aEmail;bEmail;cEmail",
"BPContPWID": "aPWID;bPWID;cPWID"
}
map = { "BPContName" : "name", "BPContEmail": "email", "BPContPWID": "pwdid" }
const result = _.reduce(o, (arr, v, k) => ( v.split(";").forEach((x,i) => _.set(arr, `${i}.${map[k]}`, x)), arr ), [])
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
You can use split() to split the values into an array.
Then iterate over the array and create the require json and then push that into results.
Check this out.
var data = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
}
var names = data.BPContName.split(';');
var emails = data.BPContEmail.split(';');
var pwids = data.BPContPWID.split(';');
var results = [];
for(var i = 0 ; i < names.length; i++) {
var obj = {
name: names[i],
email: emails[i],
pwdid: pwids[i]
}
results.push(obj);
}
console.log(results)
You could reduce the entries returned by Object.entries like this:
let obj = {
"BPContName": "aName;bName;cName",
"BPContEmail": "aEmail;bEmail;cEmail",
"BPContPWID": "aPWID;bPWID;cPWID"
}
let bpTableDataName = Object.entries(obj).reduce((r, [key, value]) => {
let splits = value.split(";");
key = key.replace("BPCont", "").toLowerCase();
splits.forEach((split, i) => (r[i] = r[i] || {})[key] = split)
return r;
}, [])
obj.bpTableDataName = bpTableDataName;
console.log(obj)
Object.entries returns an array of key-value pair. Loop through each of them
split the each value at ;
get the key by removing BPCont part and making it lowerCase
Loop through the splits and update specific keys of objects at each index
Update:
Since you have an extra d in the output's key, you can create a mapping object:
propertyMap = {
"BPContName": "name",
"BPContEmail": "email",
"BPContPWID": "pwdid"
}
And inside the reduce, change the replace code to this:
key = propertyMap[key]
Using Object.assign, Object.entries, Array#map and the spread operator make this trivial
const inputdata = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
};
const t1=Object.assign({},...Object.entries(inputdata).map(([k,v])=>({[k]:v.split(';')})));
inputdata.bpTableDataName=t1.BPContName.map((name,i)=>({name,email:t1.BPContEmail[i],pwdid:t1.BPContPWID[i]}));
console.log(inputdata);
Of course, it wouldn't be me without a one-liner
const obj = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
};
// one line to rule them all
obj.bpTableDataName=Object.entries(obj).reduce((r,[k,v])=>(v.split(';').forEach((v,i)=>(r[i]=r[i]||{})[{BPContName:'name',BPContEmail:'email',BPContPWID:'pwdid'}[k]]=v),r),[]);
//
console.log(obj);
Basically what you need is to zip it.
Snippet:
let obj = {"BPContName":"aName;bName;cName","BPContEmail":"aEmail;bEmail;cEmail","BPContPWID":"aPWID;bPWID;cPWID"},
res = _.zipWith(
..._.map(obj, v => v.split(';')),
(name, email, pwid) => ({name, email, pwid})
);
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Note, the sequence of the parameters we have to put such a way, the original object give us values when using Object.values or giving us keys when using Object.keys usually it is alphabetical order. But, In case in any env the order is not guranted we can sort it with a sequence of keys as a metadata.
Or else you can explicitly pass the arguments like:
(obj.BPContName.split(';'), obj.BPContEmail.split(';'), obj.BPContPWID.split(';'))
You can use lodash's _.flow() to create a function. Use _.map() with _.overArgs() to create a function that splits the values, format the key, and then converts them to an array of pairs using _.unzip(), for example [['name', 'x'], ['name', 'y']]. Transpose the array of arrays with _.unzip() to combine pairs of different properties. Then use _.map() to iterate, and convert each array of pairs to an object using _.fromPairs().
const { flow, partialRight: pr, map, unzip, overArgs, times, size, constant, split, fromPairs } = _
const keysMap = new Map([['BPContName', 'name'], ['BPContEmail', 'email'], ['BPContPWID', 'pwdid']])
const formatKey = key => keysMap.get(key)
const splitVals = pr(split, ';')
const fn = flow(
pr(map, overArgs(
(vals, k) => unzip([vals, times(size(vals), constant(k))]),
[splitVals, formatKey])
),
unzip, // transpose
pr(map, fromPairs) // convert each pairs array to object
)
const data = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
}
const results = fn(data)
console.log(results)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Categories