Angular 2 sorting with lodash

China☆狼群 提交于 2019-12-12 10:18:19

问题


Component:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as _ from 'lodash';

@Component({
  selector: 'app-ore-table',
  templateUrl: './ore-table.component.html',
  styleUrls: ['./ore-table.component.less']
})
export class OreTableComponent implements OnInit {
  ores = '../assets/json/ores.json';
  prices = 'https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility';

  oreArray: any;
  pricesArray: any;
  joinedArray: Array<any> = [];
  completeArray: Array<any> = [];

  seconds: number;
  turrets: any;
  turretYield: any;
  duration: any;

  constructor(private http: HttpClient) {
    this.seconds = 3600;
    this.turrets = 2;
    this.turretYield = 1593;
    this.duration = 106.9;
  }

  getOres() {
    this.http.get(this.ores).subscribe(data => {
      this.oreArray = data;
      this.getPrices();
    });
  }

  getPrices() {
    this.http.get(this.prices).subscribe(data => {
      this.pricesArray = data;
      this.joinPrices();
    });
  }

  joinPrices() {
    const cycles = this.seconds / this.duration;
    const totalYield = this.turretYield * this.turrets;

    this.oreArray.forEach((data) => {
      const matchingPrice = this.getMatchingPrice(data);

      const oreMined = totalYield * (1 / data.volume) * cycles;
      const hourIncome = matchingPrice.average_price.toFixed(2) * oreMined;
      const hourIncomeFormat = Number(hourIncome).toFixed();
      const isk = String(hourIncomeFormat).replace(/(.)(?=(\d{3})+$)/g, '$1,');

      if (matchingPrice !== false) {
          this.joinedArray.push({
              id: data.id,
              name: data.name,
              type: data.type,
              volume: data.volume.toFixed(2),
              average_price: matchingPrice.average_price.toFixed(2),
              max_income: isk,
              image: data.image
          });
      }
    });
    console.log(this.joinedArray);
    this.completeArray = _.sortBy(this.joinedArray, ['max_income']).reverse();
  }

  updatePrices(newTurrets, newTurretYield, newDuration) {
    console.log(newTurrets);
    this.joinedArray = [];

    const cycles = this.seconds / newDuration;
    const totalYield = newTurretYield * newTurrets;

    this.oreArray.forEach((data) => {
      const matchingPrice = this.getMatchingPrice(data);

      const oreMined = totalYield * (1 / data.volume) * cycles;
      const hourIncome = matchingPrice.average_price.toFixed(2) * oreMined;
      const hourIncomeFormat = Number(hourIncome).toFixed();
      const isk = String(hourIncomeFormat).replace(/(.)(?=(\d{3})+$)/g, '$1,');

      if (matchingPrice !== false) {
          this.joinedArray.push({
              id: data.id,
              name: data.name,
              type: data.type,
              volume: data.volume.toFixed(2),
              average_price: matchingPrice.average_price.toFixed(2),
              max_income: isk,
              image: data.image
          });
      }
    });
  }

  getMatchingPrice(data) {
    for (let i = 0; i < this.pricesArray.length; i++) {
      if (this.pricesArray[i].type_id === data.id) {
            return this.pricesArray[i];
        }
    }
    return false;
  }

  ngOnInit() {
    this.getOres();
  }
}

HTML:

<tr *ngFor="let ore of completeArray" id="{{ ore.id }}">
        <td><img src="{{ ore.image }}" alt="{{ ore.name}}" /></td>
        <td><strong>{{ ore.name }}</strong></td>
        <td class="right aligned">{{ ore.volume }} m&#179;</td>
        <td class="right aligned">{{ ore.average_price }} ISK</td>
        <td class="right aligned">{{ ore.max_income }}</td>
      </tr>

Screenshot:

I'm using lodash to sort my array by the 'max_income' field and then applying .reverse() to sort it in descending order:

this.completeArray = _.sortBy(this.joinedArray, ['max_income']).reverse();

As seen in the screenshot above, it works perfectly other than the first row. Because it starts with an 8, it's appearing first and this is completely wrong. What adjustment can I make to force the numbers to sort properly? Here as what an object looks like:

{
    "id": 17870,
    "name": "Vitreous Mercoxit",
    "type": "Mercoxit",
    "volume": "40.00",
    "average_price": "19000.04",
    "max_income": "50,964,186",
    "image": "../assets/images/Mercoxit.png"
  }

回答1:


I suspect the problem is it is compared as a string.

Try this:

    this.completeArray = _.sortBy(this.joinedArray,
                  (item) => {
                     return +item.max_income; 
                  }).reverse();

or:

this.completeArray = _.sortBy(this.joinedArray,
                      (item) => {
                         return +(item.max_income.replace(',', '')); 
                      }).reverse();



回答2:


The max_income is a string that can contain comma separators. Change the function that is passed to sortBy to convert the string to a number:

_.sortBy(this.joinedArray, item => +item.max_income.replace(',', ''))



回答3:


There's no need to use loadash here. It's better to write your own comparison function and use the native Array.sort() function.

var numberCompare = (a, b) => a - b;

var arr = ['1', '20', '31', '400,000', '5', '600', '70'];
var res = arr.map(x => +x.replace(',', '')).sort(numberCompare);

console.log(res);

If you want a reverse sort, do b - a in the above function.



来源:https://stackoverflow.com/questions/45813478/angular-2-sorting-with-lodash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!