Is there a better way of writing a function like this - javascript

The function below takes two arguments and returns an array of objects. Each object should be returned in descending order in reference to the availableBagSizes array.
I gave two examples, I want to know if there is a better solution to achieving the same output and why my solution is bad.
I need help with the third example it's not returning as expected.
function getBagCounts(clientOrders, availableBagSizes) {
// TODO: remove this hard-coded solution for test scenario
// clientOrders === [9]
// sorting the availablebag size in descending order
const newAvailableBag = availableBagSizes.sort((a, b) => b - a);
const result = [];
let newRemainder;
for (let index = 0; index < clientOrders.length; index++) {
const clientOrder = clientOrders[index];
// set the newremainder variable to clientOrder for the first loop
newRemainder = index === 0 ? clientOrder : newRemainder;
for (let j = 0; j < availableBagSizes.length; j++) {
const bagSize = newAvailableBag[j];
const count_result = Math.floor(newRemainder / bagSize);
newRemainder = newRemainder % bagSize;
const obj = {};
if (newRemainder > bagSize) {
result.push({ size: bagSize, count: 0 });
continue;
}
// checking if it is the last item in the bagSizes
if (j + 1 === availableBagSizes.length) {
// setting the newreaminder to the next number of client order
newRemainder = clientOrders[index + 1];
}
result.push({ size: bagSize, count: count_result });
}
}
return result;
}
// first example
const clientOrders = [9];
const availableBagSizes = [1, 2, 4];
const expectedoutput = [
{ size: 4, count: 2 },
{ size: 2, count: 0 },
{ size: 1, count: 1 }
];
// second example
const clientOrders = [5, 12, 12];
const availableBagSizes = [1, 2, 4];
const expectedoutput = [
{ size: 4, count: 1 },
{ size: 2, count: 0 },
{ size: 1, count: 1 },
{ size: 4, count: 3 },
{ size: 2, count: 0 },
{ size: 1, count: 0 },
{ size: 4, count: 2 },
{ size: 2, count: 1 },
{ size: 1, count: 0 }
];
// third example
const clientOrders = [4.5];
const availableBagSizes = [1, 2, 4];
const expectedoutput = [
{ size: 4, count: 1 },
{ size: 2, count: 0 },
{ size: 1, count: 0.5 }
];

It looks good to me.
You should think about performance and check of parameters if you want a good code.
if (!Array.isArray(clientOrders) || !Array.isArray(availableBagSizes)) {
return null;
}
Also you should try to use forEarch loop which is faster in performance
Making a push is slow, better make a .map((element,index)=>{return null})
It really depends how you manage your data, but I would say first loop is a forEach, and second loop you make a map. Because whatever the case in your second loop, all the time you make a push there would be no null or undefined return in your mapped array.

Related

Value change in 1 object changes in all objects in array

I have an array of objects. Each object has a key quantity and value. I want to duplicate each object in the array based on its quantity. Next, I want to manipulate only one of the duplicated object in the array. But on manipulating value of 1 object, value of all duplicated objects change. Here is my code:
let arr = [
{ id: 1, quantity: 3, value: 10 },
{ id: 2, quantity: 1, value: 5 },
{ id: 2, quantity: 5, value: 5 },
];
const newArr = [];
for (const a of arr) {
if (a.quantity > 1) {
let quantity = a.quantity;
a.quantity = 1;
while (quantity--) {
newArr.push(a);
}
}
}
arr = newArr;
arr[0].value = 1;
When I changed the value of arr[0] to 1, value field of arr[1] and arr[2] also changed to 1.
I have tried copying the object using spread operator and JSON.parse(JSON.parse()), but none has worked.
Because newArr.push(a) .a push to newArr ref to element of arr
You can edit same as :
let arr = [
{ id: 1, quantity: 3, value: 10 },
{ id: 2, quantity: 1, value: 5 },
{ id: 2, quantity: 5, value: 5 },
]
const newArr = []
for (const a of arr) {
if (a.quantity > 1) {
let quantity = a.quantity;
a.quantity = 1;
while (quantity--) {
newArr.push({...a})
}
}
}
arr = [...newArr]
arr[0].value = 1
console.log(arr)
// example for Memory Management
let a = { id: 1, quantity: 3, value: 10 }
let b = { id: 1, quantity: 3, value: 10 }
let c = arr[0]
let d = {...arr[0]}
console.log(a === arr[0]) // false : different allocates memory for contain value
console.log(a === b) // false : different allocates memory for contain value
console.log(c === arr[0]) // true : refer to a memory
console.log(d === arr[0]) // false : different allocates memory for contain value

Check if variables are equal to each other

I was wondering how you can check if variables are equal to each other. I have around 10 variables and I want to check if some of them are equal to each other, and if they are they should be in their own array
const user1TeamID = 2
const user2TeamID = 4
const user3TeamID = 2
const user4TeamID = 3
const user5TeamID = 1
const user6TeamID = 3
const user7TeamID = 4 ... so on
EDIT:
So I have 10 users that have a team, and I want to filter all users into their teams ID, so my output is an array
How can I do that?
I think you have to rearrange your declaration. Instead of storing teamID at a variable with a userID prefix, you should use an array of objects for storing your data. You can follow this structure.
const teams = [
{
teamID: 1,
users: [1, 2, 4]
},
{
teamID: 2,
users: [3, 5, 7]
},
{
teamID: 3,
users: [6, 9]
},
...
]
first of all you have to learn about arrays and objects in javascript, there are planty of things you can do with them and they make things easy from the API to the front
if I were you I will do like this
1st- make an object containing all all your variables (users)
2nd- get all the unique teamIDs (teams)
3rd- group the users by the team
something like that
//those are the users
let users = [
{
userID: 1,
teamID: 2
},
{
userID: 2,
teamID: 4
},
{
userID: 3,
teamID: 2
},
{
userID: 4,
teamID: 3
},
{
userID: 5,
teamID: 1
},
{
userID: 6,
teamID: 3
},
{
userID: 7,
teamID: 4
},
]
//those are the teamListId
let teamListId = [...new Set(users.map(user => user.teamID))]
//grouped users by team
teamListId.map(teamID => ({
teamID,
users: users.filter(user => user.teamID == teamID).map(el => el.userID)
})
That could be simply as folowing:
const __get = (name) => { return eval(name) };
const idList = {};
for (let i = 1; i <= 10; i++) {
const name = `user${i}TeamID`, id = __get(name);
if (idList[id] === undefined) idList[id] = [];
idList[id].push(name);
}
console.log(idList);
for array type output:
const __get = (name) => { return eval(name) };
const idxList = {}, idArray = [];
for (let i = 1; i <= 10; i++) {
const name = `user${i}TeamID`, id = __get(name), index = idArray.length-1;
if (idxList[id]) {
index = idxList[id];
idArray[index][id].push(name);
} else {
idxList[id] = ++index;
idArray.push({});
idArray[index][id] = [name];
}
}
console.log(idArray);

Javascript list loop/recursion to create an object

I'm trying to create a function to process a list of numbers relating to depth using recursion or loops in JavaScript.
The following "input" needs to be processed into the "output", and it needs to work for arbitary lists.
One thing to note is that numbers increase by either 0 or 1 but may decrease by any amount.
var input = [0, 1, 2, 3, 1, 2, 0]
var output =
[ { number: 0, children:
[ { number: 1, children:
[ { number: 2, children:
[ { number: 3, children: [] } ]
}
]
}
, { number: 1, children:
[ { number: 2, children: [] } ]
}
]
}
, { number: 0, children: [] }
]
I worked it out myself, although it needs some refinement.
var example = [0, 1, 2, 2, 3, 1, 2, 0]
var tokens = []
var last = 0
const createJSON = (input, output) => {
if (input[0] === last) {
output.push({ num: input[0], children: [] })
createJSON(input.splice(1), output)
}
else if (input[0] > last) {
last = input[0]
output.push(createJSON(input, output[output.length-1].children))
}
else if (input[0] < last) {
var steps = input[0]
var tmp = tokens
while (steps > 0) {
tmp = tmp[tmp.length-1].children
steps--
}
tmp.push({ num: input[0], children: [] })
createJSON(input.splice(1), tmp)
}
}
createJSON(example, tokens)
console.log(tokens)
In fact, it's a very simple problem to solve...
var input = [0, 1, 2, 3, 1, 2, 0]
, output = []
, parents = [output]
;
for(el of input)
{
let nv = { number:el, children:[] }
parents[el].push( nv )
parents[++el] = nv.children // save the #ddress of children:[] for adding items on
}
console.log( output )
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's a functional solution based on recursion and Array.prototype.reduce:
const data = [0, 1, 2, 3, 1, 2, 0]
const last = xs => xs.length > 0 ? xs[xs.length - 1] : undefined
const lastD = (d, t, i = 0) => i > d ? t : lastD(d, last(t).children, i + 1)
const buildIt = xs => xs.reduce(
(a, x) =>((x === 0 ? a : lastD(x - 1, a)).push({ number: x, children: [] }), a),
[]
)
console.log(buildIt(data))
.as-console-wrapper { max-height: 100% !important; top: 0; }
Note: This solution does not depend on the mutation of additional variables for bookkeeping purposes.
Turns out the actual problem was significantly simpler to solve than my initial misinterpretation!

Remove all keys that have the same value in array

I need to remove all keys except last inserted that have the same value on key id_ask in array but I'm learning javascript and I still do not know how to do this.
jQuery(function()
{
let arr = []
let q = []
$("body").on('click', '.link_resposta', function(event)
{
event.preventDefault();
/* Act on the event */
let id_poll = $(this).data("idpesquisa")
let id_ask = $(this).data("idpergunta")
let id_anwser = $(this).children("li").data("idresposta")
let q = {
id_poll,
id_ask,
id_anwser
}
arr.push(q)
console.log(arr)
});
});
Using a combination of Set, Array.reverse() and Array.map we can solve this easily.
We first use the Set and we map our source array in, just feeding the id_ask field. From that we get an array of unique id_ask.
We then map the unique id_ask array and for each id_ask we call a find() on the source array in reverse.
Comments inline.
const sampleArray = [
{
id: 1,
id_ask: 2,
id_answer: 3
},
{
id: 2,
id_ask: 2,
id_answer: 5
},
{
id: 3,
id_ask: 3,
id_answer: 3
},
{
id: 4,
id_ask: 3,
id_answer: 1
},
{
id: 5,
id_ask: 4,
id_answer: 3
}
];
// Create a unique Set of Ask ID
const uniqueAskId = [...new Set(sampleArray.map(e => e.id_ask))];
console.log(uniqueAskId);
// Use Map and Reverse to get last item.
const r = uniqueAskId.map(uid => sampleArray.reverse().find(ask => ask.id_ask === uid));
console.log(r);
Here it is as a single statement:
const sampleArray = [
{
id: 1,
id_ask: 2,
id_answer: 3
},
{
id: 2,
id_ask: 2,
id_answer: 5
},
{
id: 3,
id_ask: 3,
id_answer: 3
},
{
id: 4,
id_ask: 3,
id_answer: 1
},
{
id: 5,
id_ask: 4,
id_answer: 3
}
];
// put together in a single statement.
const result = [...new Set(sampleArray.map(e => e.id_ask))]
.map(uid => sampleArray.reverse().find(ask => ask.id_ask === uid));
console.log(result);
NOTE: For large datasets it would obviously be more efficient to call the reverse() one time before you use.
const revArray = myArray.reverse();
const resultArray = [...new Set(revArray.map(e => e.id_ask))]
.map(uid => revArray.reverse().find(ask => ask.id_ask === uid));

Remove duplicate elements from an unsorted array without using any inbuilt function or without using any other array variable in node js?

Hi in my first nodejs interview interviewer ask me to remove all duplicate elements from an unsorted array without using any inbuilt function using java script in minimum TC and without using any other array.
This is my efforts.
var input = [1, 2, 3, 3, 4, 5,2, 6,3,6,1];
var current = input[0];
var found = false;
function removeDuplicate() {
for (var i = 0; i < input.length; i++) {
if (current == input[i]) {
//found = false;
} else if (current != input[i]) {
console.log(" " + current);
current = input[i];
found = false;
}
}
console.log(" " + current);
}
removeDuplicate();
I don't really understand precisely what inbuild functions are or to what extent is a function inbuilt, so I'm assuming I'm not allowed to use indexOf, hasOwnProperty, Array.prototype.push, ...
const input = [1, 2, 3, 3, 4, 5,2, 6,3,6,1];
function removeDuplicate(arr) {
const result = [];
let idx = 0;
const tmp = {};
for (let i = 0; i < arr.length; i++) {
if (!tmp[arr[i]]) {
tmp[arr[i]] = 1;
result[idx] = arr[i];
idx++;
}
}
return result;
}
console.log(removeDuplicate(input));
If you want to remove the elements in place, then the best I can do is save the elements in place, and give the length of the eventual array. But in JavaScript, it's actually valid since arrays in JavaScript are just objects that are enumberable with an extra property length.
const input1 = [1, 2, 3, 3, 4, 5,2, 6,3,6,1];
const input2 = [1, 2, 3, 3, 4, 5,2, 6,3,6,7];
function removeDuplicate(arr) {
let length = 0;
const tmp = {};
for (let i = 0; i < arr.length; i++) {
if (!tmp[arr[i]]) {
tmp[arr[i]] = 1;
arr[length] = arr[i];
length++;
}
}
// the last element is not a duplicate
if (!tmp[arr[arr.length-1]]) {
length--;
}
arr.length = length;
return arr;
}
console.log(removeDuplicate(input1));
console.log(removeDuplicate(input2));
One line of vanilla JavaScript with no loops
Since this seems like a homework then at least make some effort to make the solution interesting.
This is my first solution but it uses a built-in .filter() method:
const removeDuplicate = (c=>a=>a.filter(e=>!(c[e]||(c[e]=1)&&0)))({});
Here is another solution without using built-ins:
const f = (c=>(h,...r)=>h?(c[h]|=0)||c[h]++?f(...r):[h,...f(...r)]:[])({});
const removeDuplicate = a => f(...a);
Here you go. One line of vanilla JavaScript plus a convenience wrapper- the second line is so you can use:
console.log(removeDuplicate(input));
// or with literals:
console.log(removeDuplicate([1, 2, 3, 3, 4, 5, 2, 6, 3, 6, 1]));
but if you're fine with this:
console.log(f(...input));
// or with literals:
console.log(f(1, 2, 3, 3, 4, 5, 2, 6, 3, 6, 1));
then you can remove the second line (and of course rename f to something better).
let arrayB = [
{id: 1, name: "abc"},
{id:2, name: "abccc"},
{id: 2, name: "xyz"},
{id:3, name: "abccc"},
{id: 4, name : "asdada"}
];
function findRepeatedObject(arr){
var newObj={};
var newArr=[];
for(i=0;i<arr.length; i++){
if(newObj[arr[i].id]){
newObj[arr[i].id]+=1;
}else{
newObj[arr[i].id]=1;
newArr.push(arr[i])
}
}
return newArr;
}
console.log(findRepeatedObject(arrayB));
//output will be [{ id: 1, name: 'abc' },{ id: 2, name: 'abccc' },{ id: 3, name: 'abccc' },{ id: 4, name: 'asdada' }];
var arr=[
{id: 1, "name": "kumar"},
{id: 1, "name": "kumar"},
{id: 2, "name": "kumar1"},
{id: 2, "name": "kumar1"},
{id: 3, "name": "kumar2"}
];
var res=[];
var count={};
arr.forEach((el,ind)=>{
count[el.id]=(count[el.id] || 0)+1;
if(count[el.id]<2){
res.push(el);
}
})
console.log(res)//[{ id: 1, name: 'kumar' },{ id: 2, name: 'kumar1' },{ id: 3, name: 'kumar2' }]enter code here

Categories

Resources