【问题标题】:Angular 2 sorting with lodash使用 lodash 进行 Angular 2 排序
【发布时间】:2017-08-22 09:13:26
【问题描述】:

组件:

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>

截图:

我正在使用 lodash 按'max_income' 字段对我的数组进行排序,然后应用.reverse() 对其进行降序排序:

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

如上面的屏幕截图所示,除了第一行之外,它可以完美运行。因为它以 8 开头,所以它首先出现,这是完全错误的。我可以进行哪些调整来强制数字正确排序?这是一个对象的样子:

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

【问题讨论】:

  • isk 是一个字符串,请尝试使用数字。
  • 您应该在 json 中使用数字而不是字符串来表示 volume、average_price 和 max_income。

标签: angular sorting lodash


【解决方案1】:

我怀疑问题是它被比较为一个字符串。

试试这个:

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

或:

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

【讨论】:

  • 谢谢,但我不确定这是做什么的。现在的顺序是无意义的:16,189,410 - 50,964,186 - 14,863,986 - 15,117,555...
  • @JoeBerthelot 我写的代码将 max_income 作为数字返回,但问题是它没有正确处理字符串中的逗号。您可以尝试将逗号替换为'',然后检查。
  • 谢谢,有没有支持多列在loadash中排序的方法?
【解决方案2】:

max_income 是一个可以包含逗号分隔符的字符串。更改传递给sortBy 的函数以将字符串转换为数字:

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

【讨论】:

    【解决方案3】:

    这里不需要使用loadash。最好自己写比较函数,使用原生的Array.sort()函数。

    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);

    如果你想要反向排序,在上面的函数中做b - a

    【讨论】:

      猜你喜欢
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 2022-07-22
      相关资源
      最近更新 更多