Reputation: 111
I have Items
data which I am attempting to display array values sorted by cost
field in costtable
array when roomname
is Double
and type
is 2
.Here is my code:
Json:
{
"index": 1,
"id": "5e3961face022d16a03b1de9_1023632_1004876",
"costtable": [
{
"roomname": "Single",
"room_id": "1023632_479490,1004876_385485",
"family": [
{
"title": "adult 1",
"cost": 3.7568000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 2,
"id": "5e3961face022d16a03b1de9_1088496_1005362",
"costtable": [
{
"roomname": "Double",
"room_id": "1088496_447339,1005362_415279",
"family": [
{
"title": "adult 1",
"cost": 5.6868000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 3,
"id": "5e3961face022d16a03b1de9_1141859_1005529",
"costtable": [
{
"roomname": "Single",
"room_id": "1141859_74888,1005529_870689",
"family": [
{
"title": "adult 1",
"cost": 5.9586000,
"unit": "10",
"type": "2"
}
]
}
]
}
]
Code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
Items: [],
library: null,
perPage: 20,
currentPage: 1,
maxPage: null,
}
}
componentDidMount() {
fetch('/json', {
method: 'GET',
})
.then(response => response.text())
.then(text => {
let Maindata = JSON.parse(text.replace(/\'/g, '"'))
let CostSort = Maindata.map(a => {
return this.renderSort(a)
})
Maindata.sort((a, b) => a.CostSort - b.CostSort);
this.setState(state => ({
...state,
Items: Maindata
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { perPage, Items } = this.state;
let library = Items;
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
renderSort(element) {
let indents = []
let lenFamilies = element.costtable.length
for (let i = 0; i < lenFamilies; i++) {
if (element.costtable[i].roomname.indexOf('Double') > -1) {
for (let j = 0; j < element.costtable[i].family.length; j++) {
if (element.costtable[i].family[j].type == 2) {
indents.push(element.costtable[i].family[j].cost)
break;
}
}
break;
}
}
return (indents)
}
// Previous Page
previousPage = event => {
this.setState({
currentPage: this.state.currentPage - 1
});
};
// Next Page
nextPage = event => {
this.setState({
currentPage: this.state.currentPage + 1
});
};
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return '';
}
return library[currentPage - 1].map((item, i) => (
<div className="item-list">
{item.index}
</div>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
<div className="wrapper-data">
{this.renderLibrary()}
</div>
<div class="clr"></div>
<ul id="page-numbers">
<li className="nexprevPage">
{currentPage !== 1 && (
<button onClick={this.previousPage}><span className="fa-backward"></span></button>
)}
</li>
<li className="controlsPage active">{this.state.currentPage}</li>
<li className="restControls">...</li>
<li className="controlsPage">{this.state.maxPage}</li>
<li className="nexprevPage">
{(currentPage < maxPage) && (<button onClick={this.nextPage}><span className="fa-forward"></span></button>
)}
</li>
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('Content'));
This code does not give me any errors but displays the values in an unsorted format. How can I sort it?
New Code
Maindata.sort((a, b) => {
let lenFamilies = a.costtable.length
for (let i = 0; i < lenFamilies; i++) {
if( a.costtable[i].roomname.indexOf('Double') > -1){
for (let j = 0; j < a.costtable[i].family.length; j++) {
if( a.costtable[i].family[j].type == 2){
a.costtable[i].family[j].cost- b.costtable[i].family[j].cost
}
}
}
}
}
Upvotes: 0
Views: 175
Reputation: 2722
I do not understand the exact formula that you are using to sort, but what you are doing before the sort is wrong.
In your componentDidMount
let CostSort = Maindata.map(a => { return this.renderSort(a) })
This returns an array into a variable called CostSort
and does not affect MainData
in any way.
However, later on you do this.
Maindata.sort((a, b) => a.CostSort - b.CostSort);
For first iteration, this will compare Maindata[0] and Maindata[1]. Note that there is no CostSort in either of the objects and hence you are performing operation of undefined - undefined
which is NaN
. Therefore no sorting happens.
I would suggest you use only the sort
function and do your comparison between two values there.
Maindata.sort((a, b) => {
// Do your calculation here
if(a should be before b) {
return -1;
} else {
return 1;
}
}
P.S The convention for variable in js is camelCase
and not PascalCase
. So, Maindata
should he mainData
.
EDIT: Here is a simple sort implementation which works for the above case, you can expand on it according to your full use case.
Maindata.sort((a, b) => {
let lenFamilies = a.costtable.length;
for (let i = 0; i < lenFamilies; i++) {
if (
a.costtable[i].roomname.includes("Double") &&
!b.costtable[i].roomname.includes("Double")
) {
return -1;
}
if (
!a.costtable[i].roomname.includes("Double") &&
b.costtable[i].roomname.includes("Double")
) {
return 1;
}
if (a.costtable[i].roomname.indexOf("Double") > -1) {
for (let j = 0; j < a.costtable[i].family.length; j++) {
if (a.costtable[i].family[j].type == 2) {
a.costtable[i].family[j].cost - b.costtable[i].family[j].cost;
}
}
}
}
});
Upvotes: 1
Reputation: 2132
Omitting the algorithms (bubble, quicksort, by inserting ...). There is possible of sorting in UI context.
Your json have: title | cost | unit | type
What type of sort You need? (title is string (can eg. sort alphabetically), then cost, unit & type are number (ascending + descending)
It's will be helpfull - when in future You provide only neccessary piece of code.
Here it's ellegant minimalistic function responsible for asc/desc sorting.
Firstly it's need to pass the props(which You wan't to sort) to values state.
function App() {
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState([10, 5, 12, 1, 2, 900, 602]);
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
useEffect(() => {
sortValues();
}, [ascValue]);
return (
<div>
<h3>{ascValue.toString()}</h3>
<button onClick={() => setAscValue(!ascValue)}>Toggle Asc</button>
{values.map(v => (
<p key={v}>{v}</p>
))}
</div>
);
}
Here is sorting by cost for your object:
let text = [{
"index": 1,
"id": "5e3961face022d16a03b1de9_1023632_1004876",
"costtable": [
{
"roomname": "Single",
"room_id": "1023632_479490,1004876_385485",
"family": [
{
"title": "adult 1",
"cost": 3.7568000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 2,
"id": "5e3961face022d16a03b1de9_1088496_1005362",
"costtable": [
{
"roomname": "Double",
"room_id": "1088496_447339,1005362_415279",
"family": [
{
"title": "adult 1",
"cost": 5.6868000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 3,
"id": "5e3961face022d16a03b1de9_1141859_1005529",
"costtable": [
{
"roomname": "Single",
"room_id": "1141859_74888,1005529_870689",
"family": [
{
"title": "adult 1",
"cost": 5.9586000,
"unit": "10",
"type": "2"
}
]
}
]
}
]
const App = () =>{
const usersWithName = Object.keys(text).map(function(key) {
var user = text[key];
return user.costtable[0].family[0].cost;
});
let costArray = usersWithName
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState(costArray);
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
useEffect(() => {
sortValues();
}, [ascValue]);
return (
<div>
<h3>{ascValue.toString()}</h3>
<button onClick={() => setAscValue(!ascValue)}>Toggle Asc</button>
{values.map(v => (
<p key={v}>{v}</p>
))}
</div>
);
}
export default App;
I don't have idea of performance in this case + if in your json are more costtable & family it should iterate by [i] iterator.
Upvotes: 0