Related
I have this payload which I'm trying to execute some functions on in JavaScript:
{
"markets": [
{
"mtId": 27,
"id": 1,
"cId": "27-1",
"mt": "OVER_UNDER",
"selections": [
{
"id": 1,
"price": 1.0896773820446435,
"selectionStatus": 1,
"name": "Over 0.5"
},
{
"id": 2,
"price": 12.159031085167172,
"selectionStatus": 1,
"name": "Under 0.5"
}
],
"marketName": "Over Under 0.5"
},
{
"mtId": 27,
"id": 2,
"cId": "27-2",
"mt": "OVER_UNDER",
"selections": [
{
"id": 1,
"price": 1.4531444546407393,
"selectionStatus": 1,
"name": "Over 1.5"
},
{
"id": 2,
"price": 3.207355058969988,
"selectionStatus": 1,
"name": "Under 1.5"
}
],
"marketName": "Over Under 1.5"
},
{
"mtId": 27,
"id": 3,
"cId": "27-3",
"mt": "OVER_UNDER",
"selections": [
{
"id": 1,
"price": 2.3859593325595307,
"selectionStatus": 1,
"name": "Over 2.5"
},
{
"id": 2,
"price": 1.721681322609395,
"selectionStatus": 1,
"name": "Under 2.5"
}
],
"marketName": "Over Under 2.5"
}
]
}
Basically, I want to take the markets array, map the selections and
return the array with price differences from 0.5.
I'd then like to take that array and return the value which is closest to zero.
I can get the result from this function:
export const generateNumberClosestToZero = (markets) => {
let goal = 0;
let result = markets
.map((market) =>
market.selections.reduce(function (bookPercentage, selection) {
return 0.5 - 1 / selection.price;
}, 0)
)
.reduce(function (prev, current) {
return Math.abs(current - goal) < Math.abs(prev - goal) ? current : prev;
});
return result;
};
But what I want to do is also retrieve the index of that reduced value, so I can perform operations on that specific market (e.g. markets[1] etc. ). Is there a way to do this with my code, or a better solution than what I have so far?
You could map the index along with the value and reduce only by the value.
const
generateNumberClosestToZero = (markets) => {
let goal = 0;
return markets
.map((market, index) => [
market.selections.reduce((bookPercentage, selection) => 0.5 - 1 / selection.price, 0),
index
])
.reduce((a, b) => Math.abs(b[0] - goal) < Math.abs(a[0] - goal) ? b : a);
},
data = { markets: [{ mtId: 27, id: 1, cId: "27-1", mt: "OVER_UNDER", selections: [{ id: 1, price: 1.0896773820446435, selectionStatus: 1, name: "Over 0.5" }, { id: 2, price: 12.159031085167172, selectionStatus: 1, name: "Under 0.5" }], marketName: "Over Under 0.5" }, { mtId: 27, id: 2, cId: "27-2", mt: "OVER_UNDER", selections: [{ id: 1, price: 1.4531444546407393, selectionStatus: 1, name: "Over 1.5" }, { id: 2, price: 3.207355058969988, selectionStatus: 1, name: "Under 1.5" }], marketName: "Over Under 1.5" }, { mtId: 27, id: 3, cId: "27-3", mt: "OVER_UNDER", selections: [{ id: 1, price: 2.3859593325595307, selectionStatus: 1, name: "Over 2.5" }, { id: 2, price: 1.721681322609395, selectionStatus: 1, name: "Under 2.5" }], marketName: "Over Under 2.5" }] };
console.log(generateNumberClosestToZero(data.markets));
I think this is what you're looking for.
const markets = [{"mtId": 27,"id": 1,"cId": "27-1","mt": "OVER_UNDER","selections": [{"id": 1,"price": 1.0896773820446435,"selectionStatus": 1,"name": "Over 0.5"},{"id": 2,"price": 12.159031085167172,"selectionStatus": 1,"name": "Under 0.5"}],"marketName": "Over Under 0.5"},{"mtId": 27,"id": 2,"cId": "27-2","mt": "OVER_UNDER","selections": [{"id": 1,"price": 1.4531444546407393,"selectionStatus": 1,"name": "Over 1.5"},{"id": 2,"price": 3.207355058969988,"selectionStatus": 1,"name": "Under 1.5"}],"marketName": "Over Under 1.5"},{"mtId": 27,"id": 3,"cId": "27-3","mt": "OVER_UNDER","selections": [{"id": 1,"price": 2.3859593325595307,"selectionStatus": 1,"name": "Over 2.5"},{"id": 2,"price": 1.721681322609395,"selectionStatus": 1,"name": "Under 2.5"}],"marketName": "Over Under 2.5"}];
const generateNumberClosestToZero = (markets) => {
let closest = 9999; // closest value found so far
let index = []; // output
markets.forEach((m, n) => {
m.selections.forEach((s, t) => {
if (s.price < closest) { // if closer value found
closest = s.price; // set closest value to new value
index[0] = n; // store market index
index[1] = t; // store selections index
}
})
});
return index;
};
const closest = generateNumberClosestToZero(markets);
console.log(closest); // get indexes
console.log(markets[closest[0]].selections[closest[1]]); // access results from market
Output:
[
0,
0
]
{
"id": 1,
"price": 1.0896773820446435,
"selectionStatus": 1,
"name": "Over 0.5"
}
I have old and entity arrays:
var old = [
{
"id": 3,
"entity_type_id": 1,
"product_id": 4,
"name": "test1",
"acreage": 100,
"yield": 20,
"worth": 30
},
{
"id": 4,
"entity_type_id": 1,
"product_id": 4,
"name": "test2",
"acreage": 10,
"yield": 20,
"worth": 0
},
{
"id": 5,
"entity_type_id": 3,
"product_id": 5,
"name": "test3",
"acreage": 20,
"yield": 20,
"worth": 40
}
]
var entity = [
{"id": 1, "name": "a1"},
{"id": 2, "name": "a2"},
{"id": 3, "name": "a3"}
]
I hope to get the following data:
var newArr = [
{
"id": 3,
"entity_type_id": 1,
"product_id": 4,
"name": "test1",
"acreage": 110,
"yield": 40,
"worth": 30,
"entity_type_1": 2, // The total amount of entity_type_id (entity_type_id: 1)
"entity_type_2": 0,
"entity_type_3": 0
},
{
"id": 5,
"entity_type_id": 3,
"product_id": 5,
"name": "test3",
"acreage": 20,
"yield": 20,
"worth": 40,
"entity_type_1": 0,
"entity_type_2": 0,
"entity_type_3": 1 // The total amount of entity_type_id (entity_type_id: 3)
}
]
console.log(newArr)
I tried the following code and got some data. I'm not sure if there will be any exceptions or errors.
What's more, I don't know how to deal with the entity array data. Can someone help me solve this problem and get the result I expect?
Thank you very much !
function mergeArr(arr) {
const temp = []
arr.forEach((dataItem) => {
if (temp.length) {
let filterValue = temp.filter((items) => {
return items.product_id === dataItem.product_id
})
if (filterValue.length) {
temp.forEach((n) => {
if (n.product_id === filterValue[0].product_id) {
n.yield = dataItem.yield + filterValue[0].yield
n.acreage = dataItem.acreage + filterValue[0].acreage
n.worth = dataItem.worth + filterValue[0].worth
}
})
} else {
temp.push(dataItem)
}
} else {
temp.push(dataItem)
}
})
return temp
}
Youi could find the object and sum the wanted properties. For entity take another loop and map new entries and build a new object from it for spreading.
var old = [{ id: 3, entity_type_id: 1, product_id: 4, name: "test1", acreage: 100, yield: 20, worth: 30 }, { id: 4, entity_type_id: 1, product_id: 4, name: "test2", acreage: 10, yield: 20, worth: 0 }, { id: 5, entity_type_id: 3, product_id: 5, name: "test3", acreage: 20, yield: 20, worth: 40 }],
entity = [{ id: 1, name: "a1" }, { id: 2, name: "a2" }, { id: 3, name: "a3" }],
entityTypes = Object.fromEntries(entity.map(({ id }) => ['entity_type_' + id, 0])),
result = old.reduce((r, o) => {
let temp = r.find(q => q.product_id === o.product_id);
if (!temp) r.push(temp = { ... o, ...entityTypes });
else ['acreage', 'yield', 'worth'].forEach(k => temp[k] += o[k]);
temp['entity_type_' + o.entity_type_id]++;
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Below is my json stored in :
$scope.regions = [];
{
"id": 100,
"regions": [
{
"id": 10,
"name": "Abc",
"rank": 0,
},
{
"id": 20,
"name": "Pqr",
"rank": 1,
},
{
"id": 30,
"name": "Lmn",
"rank": 2,
},
{
"id": 40,
"name": "xyz",
"rank": 3,
},
{
"id": 50,
"name": "GGG",
"rank": 4,
},
{
"id": 60,
"name": "YYY",
"rank": 5,
}
]
}
This is my another json stored in :
$scope.regionList = [];
var highestOrder = 3;
"regions": [
{
"id": 40,
"name": "xyz",
"rank": 0,
},
{
"id": 50,
"name": "GGG",
"rank": 1,
},
{
"id": 60,
"name": "YYY",
"rank": 2,
}
Now I want to merge $scope.regionList in to $scope.regions but for those records which are matching in both $scope.regionList and $scope.regions I would like to replace records of $scope.regions with $scope.regionList (only common records from both list).
And first non matching records from $scope.regionList will have order start using highestOrder and will keep incrementing for each non-matching records so final output will be like below :
Expected output :
"regions": [
{
"id": 10,
"name": "Abc",
"rank": 3,
},
{
"id": 20,
"name": "Pqr",
"rank": 4,
},
{
"id": 30,
"name": "Lmn",
"rank": 5,
},
{
"id": 40,
"name": "xyz",
"rank": 0,
},
{
"id": 50,
"name": "GGG",
"rank": 1,
},
{
"id": 60,
"name": "YYY",
"rank": 2,
}
As Abc is is the first non matching record so it will have order 3 and rest other will have order no from 3 i.e 4,5 6, etc.
My code:
var highestOrder = 3;
var found = false;
for (var i = 0; i < $scope.regions.length; i++) {
if ($scope.regions[i].id == 100) {
found = true;
for (var j = 0; j < $scope.regionList.length; j++) {
for (var k = 0; k < $scope.regions[i].regions.length; k++) {
if ($scope.regions[i].regions[k].id == $scope.regionList[j].id) {
$scope.regions[i].regions[k].rank = $scope.regionList[j].rank;
}
else {
$scope.regions[i].regions[k].rank = highestOrder;
highestOrder = highestOrder + 1;
}
}
}
}
if (found)
break;
}
var regions = {
"id": 100,
"regions": [{
"id": 10,
"name": "Abc",
"rank": 0,
},
{
"id": 20,
"name": "Pqr",
"rank": 1,
},
{
"id": 30,
"name": "Lmn",
"rank": 2,
},
{
"id": 40,
"name": "xyz",
"rank": 3,
},
{
"id": 50,
"name": "GGG",
"rank": 4,
},
{
"id": 60,
"name": "YYY",
"rank": 5,
}
]
}
var highestOrder = 3;
var found = false;
var regionList = [{
"id": 40,
"name": "xyz",
"rank": 0,
},
{
"id": 50,
"name": "GGG",
"rank": 1,
},
{
"id": 60,
"name": "YYY",
"rank": 2
}
]
for (var i = 0; i < regions.length; i++) {
if (regions[i].id == 100) {
found = true;
for (var j = 0; j < regionList.length; j++) {
for (var k = 0; k < regions[i].regions.length; k++) {
if (regions[i].regions[k].id == regionList[j].id) {
regions[i].regions[k].rank = regionList[j].rank;
} else {
regions[i].regions[k].rank = highestOrder;
highestOrder = highestOrder + 1;
}
}
}
}
if (found)
break;
}
console.log(regions)
You could use a hash table and build it with the elements of the array for updating.
Then iterate regions and update rank with either the hash's rank or with highestOrder. Increment highestOrder after assigning.
var $scope = { regions: [{ id: 100, regions: [{ id: 10, name: "Abc", rank: 0, }, { id: 20, name: "Pqr", rank: 1, }, { id: 30, name: "Lmn", rank: 2, }, { id: 40, name: "xyz", rank: 3, }, { id: 50, name: "GGG", rank: 4, }, { id: 60, name: "YYY", rank: 5, }] }] },
regionsUpdate = [{ id: 40, name: "xyz", rank: 0, }, { id: 50, name: "GGG", rank: 1, }, { id: 60, name: "YYY", rank: 2, }],
regionsId = 100,
highestOrder = 3,
hash = Object.create(null);
regionsUpdate.forEach(function (a) {
hash[a.id] = a;
});
$scope.regions.some(function (a) {
if (a.id === regionsId) {
a.regions.forEach(function (b) {
b.rank = hash[b.id] ? hash[b.id].rank : highestOrder++;
});
return true;
}
});
console.log($scope);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have the array:
var tabs = [
{"id": 1, "Name": "Top", "Paris": 1, "London": 1, "Rome": 1},
{"id": 2, "Name": "Best", "Paris": 1, "London": 0, "Rome": 0},
{"id": 3, "Name": "Cheap", "Paris": 0, "London": 1, "Rome": 0}
];
How can I write a function that receives as argument one of the towns (London or Paris or Rome) different each time and returns the elements of the array which the argument is 1? For example, I want to take all the elements where London=1.
var tabs= [
{ "id": 1, "Name": "Top","Paris":1,"London":1, "Rome":1},
{ "id": 2, "Name": "Best","Paris":1,"London":0,"Rome":0},
{ "id": 3, "Name": "Cheap","Paris":0,"London":1,"Rome":0}
];
var getElementsWith=function(array,name){
var myElements=[];
array.forEach(function(tab){
if(tab[name]===1)
myElements.push(tab);
});
return myElements;
};
console.log(getElementsWith(tabs,"Paris"));
You can use Array.filter:
function filterList(cityName) {
return tabs.filter(function(o) {
return o[cityName] === 1;
});
}
You could use a generic function, which takes the array, key and value, you are looking for. Then use Array#filter for the sub set.
function filter(array, key, value) {
return array.filter(function (object) {
return object[key] === value;
});
}
var tabs = [{ "id": 1, "Name": "Top","Paris":1,"London":1, "Rome":1 },{ "id": 2, "Name": "Best","Paris":1,"London":0,"Rome":0 },{ "id": 3, "Name": "Cheap","Paris":0,"London":1,"Rome":0 }],
result = filter(tabs, 'London', 1);
console.log(result);
I tried the following code.
var SeatWithCat = [{
"level": "Level II",
"price": 5,
"quantity": 1,
"seats": "B3"
}, {
"level": "Level II",
"price": 5,
"quantity": 1,
"seats": "B1"
}, {
"level": "Level I",
"price": 10,
"quantity": 1,
"seats": "A2"
}, {
"level": "Level III",
"price": 30,
"quantity": 1,
"seats": "C1"
}, {
"level": "Level III",
"price": 30,
"quantity": 1,
"seats": "C2"
}, {
"level": "Level V",
"price": 50,
"quantity": 1,
"seats": "E1"
}, {
"level": "Level II",
"price": 5,
"quantity": 1,
"seats": "B2"
}, {
"level": "Level VI",
"price": 2,
"quantity": 1,
"seats": "F1"
}];
var temp = [];
var jsonarr = [];
for (var i = 0; i < SeatWithCat.length; i++) {
for (var j = 1; j < SeatWithCat.length; j++) {
if (SeatWithCat[i].level === SeatWithCat[j].level) {
temp.push({
level: SeatWithCat[i].level,
quantity: SeatWithCat[i].quantity + SeatWithCat[j].quantity,
price: SeatWithCat[i].price + SeatWithCat[j].price,
seats: SeatWithCat[i].seats + "," + SeatWithCat[j].seats
});
SeatWithCat = SeatWithCat.filter(function(el) {
return el.level !== SeatWithCat[i].level;
});
jsonarr = SeatWithCat;
alert(JSON.stringify(temp));
}
}
}
var finalObj = temp.concat(jsonarr);
alert(JSON.stringify(finalObj));
Output:
[{
"level": "Level II",
"quantity": 2,
"price": 10,
"seats": "B3,B1"
}, {
"level": "Level III",
"quantity": 2,
"price": 60,
"seats": "C1,C1"
}, {
"level": "Level VI",
"quantity": 2,
"price": 4,
"seats": "F1,F1"
}, {
"level": "Level I",
"price": 10,
"quantity": 1,
"seats": "A2"
}, {
"level": "Level V",
"price": 50,
"quantity": 1,
"seats": "E1"
}]
It's Working fine for two objects having same level but if there are greater than two objects in the array with same level its not working. My requirement is to add values for any number of objects having same level.
Thanks in advance!
You can use Array.prototype.reduce() to collect unique items in an dictionary, and then transform the dictionary back to array using Array.prototype.map():
function combine(arr) {
var combined = arr.reduce(function(result, item) {
var current = result[item.level];
result[item.level] = !current ? item : {
level: item.level,
price: current.price + item.price,
quantity: current.quantity + item.quantity,
seats: current.seats + ',' + item.seats
};
return result;
}, {});
return Object.keys(combined).map(function(key) {
return combined[key];
});
}
var SeatWithCat = [{"level":"Level II","price":5,"quantity":1,"seats":"B3"},{"level":"Level II","price":5,"quantity":1,"seats":"B1"},{"level":"Level I","price":10,"quantity":1,"seats":"A2"},{"level":"Level III","price":30,"quantity":1,"seats":"C1"},{"level":"Level III","price":30,"quantity":1,"seats":"C2"},{"level":"Level V","price":50,"quantity":1,"seats":"E1"},{"level":"Level II","price":5,"quantity":1,"seats":"B2"},{"level":"Level VI","price":2,"quantity":1,"seats":"F1"}];
var result = combine(SeatWithCat);
console.log(result);
You could use a hash table as reference to the same level object in the result set.
Iterate the array and check for hash - if not set generate a new object with the actual properties. Otherwise add quantity and append seats.
This proposal uses only one loop.
var seatWithCat = [{ level: "Level II", price: 5, quantity: 1, seats: "B3" }, { level: "Level II", price: 5, quantity: 1, seats: "B1" }, { level: "Level I", price: 10, quantity: 1, seats: "A2" }, { level: "Level III", price: 30, quantity: 1, seats: "C1" }, { level: "Level III", price: 30, quantity: 1, seats: "C2" }, { level: "Level V", price: 50, quantity: 1, seats: "E1" }, { level: "Level II", price: 5, quantity: 1, seats: "B2" }, { level: "Level VI", price: 2, quantity: 1, seats: "F1" }],
result = [];
seatWithCat.forEach(function (o) {
if (!this[o.level]) {
this[o.level] = { level: o.level, price: o.price, quantity: o.quantity, seats: o.seats };
result.push(this[o.level]);
return;
}
this[o.level].quantity += o.quantity;
this[o.level].seats += ',' + o.seats;
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }