ReactJS using .sort() method mixing up results in array - javascript

I have an array of data that queries the results through a prop. I am able to obtain the data but, unable to sort it. I want all the data with MyTeam to appear first.
However, when I load this into the browser I obtain different results.
In Safari the data lists MyTeam to be the second element in the array
In Chrome, the data lists MyTeam to be the third element but, whenever I interact with them (via an onClick method) the data swaps around in a different order.
If I don't have the .sort() method, everything remains the same and nothing changes.
Is there a proper way to sort the array?
var gameList = this.props.data.sort(function(game) {
return (game.homeTeam == 'MyTeam' || game.awayTeam == 'MyTeam') ? 0 : 1;
}).map(function(game, i) {
//console.log(game.homeTeam + ' ' + game.awayTeam);
});

Array#sort compares TWO items of the array. Your compare function must have two arguments. I suggest the following:
var gameList = this.props.data.sort(function(a, b) {
var matchA = a.homeTeam === 'MyTeam' || a.awayTeam === 'MyTeam';
var matchB = b.homeTeam === 'MyTeam' || b.awayTeam === 'MyTeam';
// This will return
// -1 if matchA is true and matchB is false
// 0 if matchA and matchB are both true or both false
// 1 if matchA is false and matchB is true
return (matchB ? 1 : 0) - (matchA ? 1 : 0);
});

Related

React hooks cannot push to array who's current value is all 0 i.e. [0,0,0]

I am using hooks to push a new value to an array in a certain context. The value is always a number, and my code works everytime unless the current array value is all zeroes. See the code below, in useEffect...I am trying to push a new value '0' to homeInningScores and awayInningScores under certain condition. This always works accept for one specific instance where homeInningScores and awayInningScores are both equal to [0,0,0] in which case it doesn't push anything.
const initialState = {
homeInningScores: [],
awayInningScores: [],
}
const [homeInningScores, setHomeInningScores] = useState(
initialState.homeInningScores
)
const [awayInningScores, setAwayInningScores] = useState(
initialState.awayInningScores
)
useEffect(() => {
const isLeader = homeScore > awayScore || awayScore > homeScore
if (currentInning > innings && homeScore && !isLeader) {
setInnings(innings + 1)
//This part correctly pushes to the array UNLESS homeInningScores or awayInningScores is [0,0,0]
setHomeInningScores(homeInningScores => [...homeInningScores, 0])
setAwayInningScores(awayInningScores => [...awayInningScores, 0])
}
})
I believe the problem is coming from here:
if (currentInning > innings && homeScore && !isLeader) {
if homeScore = 0 then that is also evaluated to 'false' in javascript. You should check the homeScore == null or undefined or something like that. A number can evaluate to a boolean as 0 or 1.

Dynamically call function with multiple arguments

I'm trying to find similar items amongs a dynamic amount of arrays, For example I might have 2 or 3 arrays with data in them, and want to find the which items exist between all of them.
At the minute i've got this "working" but really ugly code which won't scale past 3 items. The GDAX, PLNX etc are all bools which I have available to tell me whether this option is selected.
The intersectionBy is a lodash helper function with further information available here https://lodash.com/docs/4.17.4#intersectionBy
let similarItems = [];
similarItems = GDAX && PLNX && BTRX ? _.intersectionBy(data.BTRX, data.PLNX, data.GDAX, 'pair') : similarItems;
similarItems = GDAX && PLNX && !BTRX ? _.intersectionBy(data.PLNX, data.GDAX, 'pair') : similarItems;
similarItems = GDAX && !PLNX && BTRX ? _.intersectionBy(data.BTRX, data.GDAX, 'pair') : similarItems;
similarItems = !GDAX && PLNX && BTRX ? _.intersectionBy(data.BTRX, data.PLNX, 'pair') : similarItems;
This should do the job
const input = ['GDAX', 'PLNX', 'BTRX']; // here you pass the strings that are given
const result = _.intersectionBy.apply(_, input.map(name => data[name]).concat(['pair']));
The input could also somehow automized, e.g. giving the object of true / false values for each name, so
const inputObject = { GDAX: true, PLNX: false, BTRX: true };
const names = ['GDAX', 'PLNX', 'BTRX'].filter(name => inputObject[name]);
const result = _.intersectionBy.apply(_, names.map(name => data[name]).concat(['pair']));
For readability and easy maintainability, I'd go with explicitly building a selection according to your boolean flags:
let selection = [];
if (GDAX) selection.push(data.GDAX);
if (PLNX) selection.push(data.PLNX);
if (BTRX) selection.push(data.BTRX);
const result = _.intersectionBy(...selection, 'pair');

React.js – filter multiple indexOf

Im just looking for a bit of advice regarding React.js filtering. I am currently filtering ‘peopleList’ by ‘employeeName’ and this is working fine, im getting back exactly what I expect.
But I wanted to also filter by the ‘employeeID’ at the same time i.e. check if ‘employeeName’ or ‘employeeID’ contain an indexOf.. Is this possible or would I need to set up two filters for 'employeeName’ and 'employeeID’?
let people= this.state.peopleList.filter(
(person) => {
return person.record.employeeName.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
// return person.record.employeeID.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
If your condition is either one OR the other, you can use the || operator
const { search, peopleList } = this.state
const searchStr = search.toLowerCase()
const people = peopleList.filter((person) =>
person.record.employeeName.toLowerCase().indexOf(searchStr) !== -1 ||
person.record.employeeId.indexOf(searchStr) !== -1
)

Sort arrays, variables or objects in Javascript

Im new to javascript but I have already made some scripts that really make a difference in my workflow. However I am now embarking on a project that forces me to sort data in a way I dont know howto do in Javascript. I will try to explain what I need to do as if my data was in excel but it isnt, I have only been able to put the data in 4 different arrays:
pagenumber[1,2,3,4,5] //only numbers
zipcode[77889,99887,33667,11122,44559] // only numbers
streetname[Hillroad, Hillroad, Baghdad Street, Hongway, Chinatown] //only letters
roadnumber[55,27,1,13,16] //only numbers
I would like to sort them like this, first by the zipcode, then by the roadname, then by the even roadnumbers descending, then by the odd roadnumbers ascending.
According to this new sorting I want to generate a new pagenumber but I want it to somehow relate to the (old) variable "pagenumber" so I can locate the old page and extract it to a new document with new pagenumbers. I am not asking you guys to write all the code for me but I need a little bit of advice to know firstly if it is possible to do which I think it is, secondly if it is right of me to put the data in four different arrays, thirdly if ther is any (ofcourse) smarter way to save the data so they relate to eachother more closely. Give me your thoughts. Also tips of where and what I should read is appreciated. Thank you all for the answers. However I want to point out that I write my code in Acrobat DC not for the web.
I suppose the items in your arrays are tied. So you should use [{},{},{},{},{}] instead of 4 arrays.
var items = [{pagenumber:1,zipcode:77889,streetname:Hillroad,roadnumber:55},{...},{...},{...},{...}]
Then sort each key-value property one-by-one, like below:
var x= [ {a:2,b:2,c:3}, {a:1,b:1,c:1}, {a:1,b:2,c:3}, {a:2,b:2,c:2} ];
x.sort(function(item1, item2){
var sort_a = item1.a-item2.a;
if (sort_a) return sort_a;
var sort_b = item1.b-item2.b;
if (sort_b) return sort_b;
var sort_c = item1.c-item2.c;
if (sort_c) return sort_c;
})
Or simplify it to be
x.sort(function(item1, item2){
return (item1.a-item2.a) || (item1.b-item2.b) || (item1.c-item2.c);
})
Given the data:
var pagenumber=[1,2,3,4,5]; //only numbers
var zipcode=[77889,99887,33667,11122,44559]; // only numbers
var streetname=['Hillroad', 'Hillroad', 'Baghdad Street', 'Hongway', 'Chinatown']; //only letters
var roadnumber=[55,27,1,13,16]; //only numbers
First, you need to make your data more easily manageable
var data = pagenumber.map(function(itemValue, index) {
return {
pagenumber:itemValue, // == pagenumber[index]
zipcode:zipcode[index],
streetname:streetname[index],
roadnumber:roadnumber[index]
};
});
Then sort it
data.sort(function(a, b) {
if (a.zipzode != b.zipcode) {
// numeric
return a.zipcode - b.zipcode;
}
if (a.streetname != b.streetname) {
// alpha
return a.streetname < b.streetname ? -1 : a.streetname > b.streetname ? 1 : 0;
}
if (a.roadnumber % 2 != b.roadnumber % 2) {
// even before odd
return b.roadnumber % 2 - a.roadnumber % 2;
}
// numeric
return a.roadnumber - b.roadnumber;
});
borrowing from another answer, that can be simplified to
data.sort(function(a, b) {
return (a.zipcode - b.zipcode) || (a.streetname < b.streetname ? -1 : a.streetname > b.streetname ? 1 : 0) || (b.roadnumber % 2 - a.roadnumber % 2) || (a.roadnumber - b.roadnumber);
});
Personally, I don't use the intermediate step when I can avoid it ... so the following is equivalent to bot the map and sort in one chained command
var sortedData = pagenumber.map(function(itemValue, index) {
return {
pagenumber:itemValue,
zipcode:zipcode[index],
streetname:streetname[index],
roadnumber:roadnumber[index]
};
}).sort(function(a, b) {
return (a.zipcode - b.zipcode) || (a.streetname < b.streetname ? -1 : a.streetname > b.streetname ? 1 : 0) || (b.roadnumber % 2 - a.roadnumber % 2) || (a.roadnumber - b.roadnumber);
});
// sorting zipcode in ascending order
zipcode.sort();
// sorting streetname in ascending order
streetname.sort();
// fetching evenroad numbers
var roadnumbereven=roadnumber.filter(function(element, index, array) {
return (element % 2 === 0);
});
// fetching odd roadnumbers
var roadnumberodd = roadnumber.filter(function(element, index, array) {
return (element % 2 !== 0);
});
// sorting even road numbers in ascending order
roadnumbereven.sort();
// sorting odd road numbers in descending order
roadnumberodd.sort(function(a,b){ return b-a; });
// merging roadnumbers(even/odd)
roadnumber = roadnumbereven.concat(roadnumberodd);
console.log(roadnumber);

Compare Objects in Array and Remove Duplicate & Update - Javascript

I have an array of objects that presents as follows:
0: Object
ConsolidatedItem_catalogId: "080808"
ConsolidatedItem_catalogItem: "undefined"
ConsolidatedItem_cost: "0"
ConsolidatedItem_description: "Test Catalog Item"
ConsolidatedItem_imageFile: "27617647008728.jpg"
ConsolidatedItem_itemNumber: "1234"
ConsolidatedItem_quantity: "1"
ConsolidatedItem_source: "CAT"
ConsolidatedItem_status: "02"
ConsolidatedItem_umCode: "EA"
1: Object
ConsolidatedItem_catalogId: ""
ConsolidatedItem_catalogItem: "undefined"
ConsolidatedItem_cost: "0"
ConsolidatedItem_description: "ALARM,SHUTDOWN SYSTEM,AXIOM,XP3, 0-1500 PSIG, HIGH AND LOW PRES Testing"
ConsolidatedItem_imageFile: ""
ConsolidatedItem_itemNumber: "10008"
ConsolidatedItem_quantity: "1"
ConsolidatedItem_source: "INV"
ConsolidatedItem_status: "02"
ConsolidatedItem_umCode: "EA"
I'm trying to update and remove an object if it's added again, or update the object. Preferably update the object with the new value. My code is as follows:
var result = $.grep(finalObject, function(e) {
return e.ConsolidatedItem_itemNumber == o.ConsolidatedItem_itemNumber;
});
console.log(result);
if (result.length == 0) {
finalObject.push(o);
shoppingCounter = finalObject.length;
$('#numberShoppedItems').text(shoppingCounter);
console.log(finalObject);
} else if (result.length == 1) {
finalObject.filter(function(x){
result = x;
console.log(result);
return x == result.ConsolidatedItem_itemNumber;
});
} else {
alert('Multiples Found');
}
}
I've tried multiple ways of getting the exact object and manipulating the data, however they've all failed. I would prefer to update the object, say if CatalogItem_itemNumber held the same value, if the CatalogItem_quantity was different - add the CatalogItem_quantity values together and update the array of objects.
I don't need an exact answer, a nudge in the right direction would do wonders though. I've looked at several of the related questions over the past couple of hours but none of them seem to address the issue. If you know of a question that has an answer, feel free to just link that as well. I may have missed it.
No Underscore.js please
When you find the matching record, you may update it by using $.extend
$.extend(result[0], o)
This will update the object in finalObject array in-place.
Alternatively, if you want to use the filter, you will need to insert the new object in the array.
finalObject = finalObject.filter(function(x) {
return x !== result[0];
});
finalObject.push(o)
Here we are allowing all the records that are not not equal to result to be returned in the resultant array that is received in finalObject. In next line, we are adding the new record.
Solved in the following manner:
1.) Verify object is not empty.
2.) Use .some() on object to iterate through it.
3.) Check if the finalObject, which is now e, has a match for the key in my temporary object I assemble, o.
4.) Update the values that need updating and return true;
Note: Originally I was going to remove the object by its index and replace it with a new object. This too can work by using .splice() and getting the index of the current object in that array you're in.
Here is the updating version:
if (o.ConsolidatedItem_quantity != '') {
var result = $.grep(finalObject, function(e) {
return e.ConsolidatedItem_itemNumber == o.ConsolidatedItem_itemNumber;
});
if (result.length == 0) {...}
else {
finalObject.some(function (e) {
if(e.ConsolidatedItem_itemNumber == o.ConsolidatedItem_itemNumber){
var a;
a = +e.ConsolidatedItem_quantity + +o.ConsolidatedItem_quantity;
e.ConsolidatedItem_quantity = a.toString();
document.getElementById(o.ConsolidatedItem_itemNumber).value=a;
return true;
};
});
}
}

Categories