How does `lookupIndex[row[lookupKey]] = row;` work? - javascript

I am reading learnjsdata.com and came across this unfamiliar JavaScript syntax. The syntax is as follows:
lookupIndex[row[lookupKey]] = row;
Anyone know what's happening here? I haven't seen syntax like this. Used in context:
Data
var articles = [{
"id": 1,
"name": "vacuum cleaner",
"weight": 9.9,
"price": 89.9,
"brand_id": 2
}, {
"id": 2,
"name": "washing machine",
"weight": 540,
"price": 230,
"brand_id": 1
}, {
"id": 3,
"name": "hair dryer",
"weight": 1.2,
"price": 24.99,
"brand_id": 2
}, {
"id": 4,
"name": "super fast laptop",
"weight": 400,
"price": 899.9,
"brand_id": 3
}];
var brands = [{
"id": 1,
"name": "SuperKitchen"
}, {
"id": 2,
"name": "HomeSweetHome"
}];
Function & Invocation
function join(lookupTable, mainTable, lookupKey, mainKey, select) {
var l = lookupTable.length,
m = mainTable.length,
lookupIndex = [],
output = [];
for (var i = 0; i < l; i++) { // loop through l items
var row = lookupTable[i];
lookupIndex[row[lookupKey]] = row; // create an index for lookup table
}
for (var j = 0; j < m; j++) { // loop through m items
var y = mainTable[j];
var x = lookupIndex[y[mainKey]]; // get corresponding row from lookupTable
output.push(select(y, x)); // select only the columns you need
}
return output;
};
var result = join(brands, articles, "id", "brand_id", function(article, brand) {
return {
id: article.id,
name: article.name,
weight: article.weight,
price: article.price,
brand: (brand !== undefined) ? brand.name : null
};
});
console.log(result);
Appreciate any answers or pointers, thanks!

Think of it as two separate function calls:
var rowLookup = row[lookupKey];
lookupIndex[rowLookup] = row;
It's the same as doing it all in the same line:
lookupIndex[row[lookupKey]] = row;

Related

How group students with different scores in leveled groups

I need to create groups of students to work together, but i need to level the groups using his grades. So, i don't want only the good grades students in one hand and the bad grades on other. I want to mix them all using his grades to randomize that.
So, i have the name and the score for every student. I need 3 homework groups, so i calculated the score of all / 3. To know the value who every single group need.
Now it's the problem, i don't know how can i insert the students in this groups without be over the max value for one group and how guarantee every group with same number of students.
Until now, i make this:
var totalScore = 0;
for (var i = 0; i < students.length; i++) {
totalScore = totalScore + students[i].score;
}
var maxScoreForGroup = totalScore / 3;
console.log(maxScoreForGroup);
for (var o = 0 ; o < students.length; o++) {
if ((students[o].score + homeWork1[0].scoreTotal) < maxScoreForGroup) {
homeWork1[0].students.push(students[o].name);
homeWork1[0].scoreTotal = homeWork1[0].scoreTotal + students[o].score;
} else if ((students[o].score + homeWork2[0].scoreTotal) < maxScoreForGroup) {
homeWork2[0].students.push(students[o].name);
homeWork2[0].scoreTotal = homeWork2[0].scoreTotal + students[o].score;
} else {
homeWork3[0].students.push(students[o].name);
homeWork3[0].scoreTotal = homeWork3[0].scoreTotal + students[o].score;
}
}
But i'm getting in homeWork1 only 2 students with score 10 each, in homework2 only 2 students with score 10 and 7.5, and in homework 3 every other student.
How can i change this to get 3 groups with 3 students and every group with the same score total?
My array of students
var students = [
{
"name": "Charles",
"score": 10
},
{
"name": "Max",
"score": 10
},
{
"name": "Samuel",
"score": 10
},
{
"name": "Carl",
"score": 7.5
},
{
"name": "James",
"score": 7.5
},
{
"name": "Frank",
"score": 7.5
},
{
"name": "George",
"score": 5
},
{
"name": "Timothy",
"score": 5
},
{
"name": "Paul",
"score": 5
},
]
My output is
"[{"scoreTotal":20,"students":["Charles","Max"]}]"
"[{"scoreTotal":17.5,"students":["Samuel","Carl"]}]"
"[{"scoreTotal":30,"students":["James","Frank","George","Timothy","Paul"]}]"
I made this fiddle too
Here's another approach that might work for you.
We shuffle the students array, split into groups of n students (in this case 3), then get the total scores of each group.
If the groups have the same total score we add to our possibleGroups array.
You can change the number of attempts or just repeat to get different groupings.
const students = [ { "name": "Charles", "score": 10 }, { "name": "Max", "score": 10 }, { "name": "Samuel", "score": 10 }, { "name": "Carl", "score": 7.5 }, { "name": "James", "score": 7.5 }, { "name": "Frank", "score": 7.5 }, { "name": "George", "score": 5 }, { "name": "Timothy", "score": 5 }, { "name": "Paul", "score": 5 }, ]
function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
function getTotalScore(a) {
return a.reduce((total, student) => total + student.score, 0);
}
function allEqual(a) {
return (new Set(a).size) === 1;
}
function split(a, groupSize) {
return a.reduce((sums, x, idx) => {
if (idx % groupSize === 0) {
sums.push([]);
}
sums[sums.length - 1].push(x);
return sums;
}, [])
}
let attempts = 20;
let n = 3;
let possibleGroups = [];
for(let i = 0; i < attempts; i++) {
let groups = split(shuffle([...students]), n);
let scores = groups.map(getTotalScore);
if (allEqual(scores)) {
possibleGroups.push( { scoreTotal: scores[0], groups } );
}
}
console.log('Possible groupings:');
possibleGroups.forEach((group, idx) => {
console.log(`Grouping ${idx + 1}:`);
console.log(JSON.stringify(group, null, 2))
})
.as-console-wrapper { max-height: 100% !important; }

Repeat every element in array based on object properties

I have an array that I'm retrieving from an API. The array looks like this:
[{
"name": "Rachel",
"count": 4,
"fon": "46-104104",
"id": 2
},
{
"name": "Lindsay",
"count": 2,
"fon": "43-053201",
"id": 3
},
{
"name": "Michael",
"count": 5,
"fon": "46-231223",
"id": 4
}]
Then I loop through the array to create an array containing only the names.
function buildName(data) {
for (var i = 0; i < data.length; i++) {
nameList.push(data[i].name)
}
}
This also works so far, but I would like to create an array in which each name occurs as often as the object count says.
For example, the name Michael should appear five times in the array and Lindsay twice.
[
"Rachel",
"Rachel",
"Rachel",
"Rachel",
"Lindsay",
"Lindsay",
"Michael",
"Michael",
"Michael",
"Michael"
"Michael"
]
For each object create a new array using count, and then fill it with the name.
If you use flatMap to iterate over the array of objects. It will return a new array of nested objects but then flatten them into a non-nested structure.
const data=[{name:"Rachel",count:4,fon:"46-104104",id:2},{name:"Lindsay",count:2,fon:"43-053201",id:3},{name:"Michael",count:5,fon:"46-231223",id:4}];
const out = data.flatMap(obj => {
return new Array(obj.count).fill(obj.name)
});
console.log(out);
I've upgraded your functions but you can use the map method
function buildName(data){
for (let i = 0; i < data.length; i++){
let numToLoop = data[i].count
let name = data[i].name
for (let z = 0; z < +numToLoop; z++){
nameList.push(name)
}
}
}
Use an inner while loop inside the for loop:
const data = [{
"name": "Rachel",
"count": 4,
"fon": "46-104104",
"id": 2
},
{
"name": "Lindsay",
"count": 2,
"fon": "43-053201",
"id": 3
},
{
"name": "Michael",
"count": 5,
"fon": "46-231223",
"id": 4
}]
function buildName(data){
const result = [];
for (let i = 0; i < data.length; i += 1) {
let item = data[i];
let count = item.count;
while (count > 0) {
result.push(item.name);
count -= 1;
}
}
return result;
}
console.log(buildName(data));
Just add an inner loop with as many iterations as the "count" property in the object:
function buildName(data) {
const nameList = [];
for (var i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].count; j++) {
nameList.push(data[i].name);
}
}
return nameList;
}
For fun
import { pipe } from 'fp-ts/lib/function';
import { chain, replicate } from 'fp-ts/lib/Array';
const arr = ...
const result = pipe(
arr,
chain(i => replicate(i.count, i.name))
);
You can use .flapMap() for that:
const arr = [{ "name": "Rachel", "count": 4, "fon": "46-104104", "id": 2 }, { "name": "Lindsay", "count": 2, "fon": "43-053201", "id": 3 }, { "name": "Michael", "count": 5, "fon": "46-231223", "id": 4 }];
const result = arr.flatMap(({count, name}) => Array(count).fill(name));
console.log(result);
Effectively you turn every element into an array of the the name property repeated count times which is then flattened into a single array.
It can be done via creating an array with repeated names in this way:
Array(count).fill(name)
Then you have to spread it into resulting array.
You can try this one-liner
const getNames = (data) =>
data.reduce(
(names, { name, count }) => [...names, ...Array(count).fill(name)],
[]
)
Note that a pure function is presented here, which is generally the preferred way of writing code. However, updating your example code might look like this
const getNames = (data) =>
data.reduce(
(names, { name, count }) => [...names, ...Array(count).fill(name)],
[]
)
function buildName(data) {
nameList = getNames(data)
}

Remove Object if Key Value don't match Input Variable after calculating and comparing with input variables

I am trying to compare input variable key/values with data in Json file, there are 200+ orders in the file, for Order_number (66 in this case) need to calculate and compare the count of line items(6 in this case) along with the Quantity of items(7 in this case), if it doesn't match need to remove Object Refund along with its elements, else leave it as it is.
The variables from the sql query result to be compared against this sample would be :
Order_number 66
count of line items 6
Quantity of items 6
I got stuck at calculating it.
File Content:
{
"app_id": 111,
"fulfillments": [],
"line_items": [
{
"id": 376,
"quantity": 2
},
{
"id": 992,
"quantity": 1
},
{
"id": 929,
"quantity": 1
},
{
"id": 768,
"quantity": 1
},
{
"id": 929,
"quantity": 1
},
{
"id": 768,
"quantity": 1
}
],
"name": "#59",
"number": 6,
"order_number": 66,
"order_id": 999,
]
}
var derivedOrderNumber = getVariable("Trans_ID", "");
var derivedNumberOfLineItems = getVariable("Count_Of_Fulfillment", "");
var derivedTotalQuantityOfItems = getVariable("Total_Quantity", "");
var jsonOrderNumber = 0;
var jsonNumberOfLineItems = 0;
var jsonTotalQuantityOfItems = 0;
//Calculate Number of Line Items and Total Quantity for order_number
let output = arr.reduce((op,cur)=>{
if(op[cur['ORDER_NUMBER']]){
op[cur['LINE_ITEMS']]['jsonTotalQuantityOfItems']+=cur['QUANTITY'];
op[cur['LINE_ITEMS']]['jsonNumberOfLineItems']++;
} else {
op[cur['ORDER_NUMBER']] ={
'jsonNumberOfLineItems' : 1,
'jsonTotalQuantityOfItems' : cur['QUANTITY'],
}
}
return op;
},{})
console.log(output);
try this
let arrSum = 0;
data.line_items.forEach((element) => {
arrSum += element.quantity;
});
if (arrSum != data.number) delete data.refunds;

theArray is not defined

I try to avoid to use $.grep to filter what needs to be filter. In my case I want to remove array of objects which has an id of '123', but I'm getting theArray is not defined error.
function filter(array, conditionFunction) {
var validValues = [];
for (var index = 0; index < array.length; i++) {
if (conditionFunction(theArray[index])) {
validValues.push(theArray[index]);
}
}
}
var cart = [
{
"id": "123456",
"name": "banana",
"image": "56fca57eb239dc38e355c86b-1459398061689-2013-Le-Tour-de-Langkawi-Stage-5-3.jpg",
"price": 12,
"discount_price": 8,
"qty": 4
},
{
"id": "123",
"name": "Christ come",
"image": "56fcb471b239dc38e355c86c-1459401869191-klcc.jpg",
"price": 12.9,
"discount_price": 11.9,
"qty": 4
}
]
cart = filter(cart, function(e) {
return e.id !== '123';
});
console.log(cart);
This ought to fix your problem. You changed your array variable to be theArray in the middle of your for-loop. Javascript can't know that, so you'll have to be more supportive and tell JS which array you mean.
for (var index = 0; index < array.length; i++) {
if (conditionFunction(array[index])) {
validValues.push(array[index]);
}
}

JavaScript compare two arrays(key/value pairs) and copy value from one to the other if key matches

I have two arrays containing key/value pairs.
{
"containerOne": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": "ValueOne"
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "ValueTwo"
}]
}
{
"containerTwo": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": null
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "null
}
]
}
I'd like to compare both arrays and compare the title of each container. If the titles match, then I'd like to copy the Responsibility value from containerOne to containerTwo. The ID's will not match, so that can be ruled out. Only the titles will be consistent.
What is the most efficient way to do this please?]
Thanks
=====================================================================
EDIT
=====================================================================
Looking at the arrays a little closer, there is a subtle difference in the data being returned:
{
"AMLookupTasksList":
[
{
"Id":1,
"Title":"Create and Maintain an Onboarding Document",
"Responsibility":"1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
},
{
"Id":2,
"Title":"Execute Onboarding for New Consultants",
"Responsibility":"1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}
]
}
{
"AMTasksList":
[
{
"Id":4,
"Title":
{
"$M_1":13,"$c_1":"Create and Maintain an Onboarding Document"
},
"Responsibility":null
},
{
"Id":17,
"Title":
{
"$M_1":12,"$c_1":"Execute Onboarding for New Consultants"
},
"Responsibility":null
}
]
}
Do I have additional looping to get to the Title value in the second array?
This might be a bit of overkill but it ignores the sequence and does a look up in each object.
I had to fix some syntax in your objects but I include that: named the objects and took a quote off one of the null values.
var obj1 = {
"containerOne": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": "ValueOne"
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "ValueTwo"
}]
};
var obj2 = {
"containerTwo": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": null
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": null
}]
};
Now the code:
// lookup for first object:
var lookup = {};
// create referece to list above and use it everywhere
lookup.list = obj1;
for (var i = 0, len = lookup.list.containerOne.length; i < len; i++) {
lookup[lookup.list.containerOne[i].Title] = lookup.list.containerOne[i];
}
// lookup for second object
var otherLookup = {};
otherLookup.list = obj2;
for (var i = 0, len = otherLookup.list.containerTwo.length; i < len; i++) {
otherLookup[otherLookup.list.containerTwo[i].Title] = otherLookup.list.containerTwo[i];
}
// copy value for Responsibility from first to second on each matched in second.
var i = 0;
var len = lookup.list.containerOne.length;
for (i; i < len; i++) {
// looks up value from second list in the first one and if found, copies
if (lookup[otherLookup.list.containerTwo[i].Title]) {
otherLookup.list.containerTwo[i].Responsibility = lookup[otherLookup.list.containerTwo[i].Title].Responsibility;
}
}
// alerts new value using lookup
alert(otherLookup["TitleOne"].Responsibility);
EDIT for new structure, but same answer really:
var obj1 = {
"AMLookupTasksList": [{
"Id": 1,
"Title": "Create and Maintain an Onboarding Document",
"Responsibility": "1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}, {
"Id": 2,
"Title": "Execute Onboarding for New Consultants",
"Responsibility": "1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}]
};
var obj2 = {
"AMTasksList": [{
"Id": 4,
"Title": {
"$M_1": 13,
"$c_1": "Create and Maintain an Onboarding Document"
},
"Responsibility": null
}, {
"Id": 17,
"Title": {
"$M_1": 12,
"$c_1": "Execute Onboarding for New Consultants"
},
"Responsibility": null
}]
};
var lookup = {};
// create refernece to list above and use it everywhere
lookup.list = obj1;
for (var i = 0, len = lookup.list.AMLookupTasksList.length; i < len; i++) {
lookup[lookup.list.AMLookupTasksList[i].Title] = lookup.list.AMLookupTasksList[i];
}
var otherLookup = {};
otherLookup.list = obj2;
for (var i = 0, len = otherLookup.list.AMTasksList.length; i < len; i++) {
otherLookup[otherLookup.list.AMTasksList[i].Title.$c_1] = otherLookup.list.AMTasksList[i];
}
// copy value for Responsibility from first to second
var i = 0;
var len = otherLookup.list.AMTasksList.length;
for (i; i < len; i++) {
if (lookup[otherLookup.list.AMTasksList[i].Title.$c_1]) {
otherLookup.list.AMTasksList[i].Responsibility = lookup[otherLookup.list.AMTasksList[i].Title.$c_1].Responsibility;
}
}
alert(otherLookup["Create and Maintain an Onboarding Document"].Responsibility);
Fiddle for second answer: http://jsfiddle.net/n22V8/
First, create a dictionary from containerTwo:
var c2dict = {};
var c2i = containerTwo.innerContainer;
for (var i = 0; i < c2i.length; i++) {
c2dict[c2i[i].Title] = c2i[i];
}
Now use this to do the copying of propertyies when titles match:
var c1i = containerOne.innerContainer;
for (var i = 0; i < c1i.length; i++) {
if (c2dict[c1i[i].Title]) {
c2dict[c1i[i].Title].Property = c1i[i].Property;
}
}
You should compare properties and set them as the following:
containerOne.innerContainer.forEach(function (element,index) {
containerTwo.innerContainer.forEach(function (element2,index2) {
if (element.Title === element2.Title && element.Property != element2.Property) {
element2.Property = element.Property;
}
});
});

Categories