【问题标题】:Sorting array of objects by price (lowest to highest)按价格排序对象数组(从最低到最高)
【发布时间】:2019-04-09 16:52:51
【问题描述】:

以下是我目前在 React.js 中制作 Web 应用程序时正在使用的一些数据,现在我正在尝试按价格从最低到最高对对象数组进行排序,以便在单击按钮时该数组已排序并从最低到最高显示在 DOM 上。

我必须考虑的几件事是价格都包含为字符串,其中第一个字符为“$”字符(例如:“$18”),数组价格中的第二个对象是“建议捐赠”。

studios: [
  {
    name: "Whole Yoga",
    price: "$17.00"
  },
  {
    name: "Rino Yoga Social",
    price: "Suggested Donation"
  },
  {
    name: "Samadhi Yoga",
    price: "$20.00"
  },
  {
    name: "Corepower Yoga",
    price: "$25.00"
  },
  {
    name: "The River Yoga",
    price: "$20.00"
  },
  {
    name: "Endorphin Yoga",
    price: "$10.00"
  },
  {
    name: "Kindness Yoga",
    price: "$20.00"
  },
  {
    name: "Yoga High",
    price: "$15.00"
  },
  {
    name: "Freyja Project",
    price: "$22.00"
  },
  {
    name: "Kula Yoga",
    price: "$17.00"
  }
 ]

到目前为止,我使用了一个 while 循环来删除字符串开头的 '$' 字符,然后使用 .replace() 方法将“Suggested Donation”替换为 '00.00' 并解析所有价格。

我现在遇到的问题是新的排序价格数组与原始数据无关(没有链接它们)所以我只是返回一个我无法做任何事情的排序价格数组。有人对我应该如何处理有任何想法吗?

priceFilter = () => {
    let newArr = []

    return this.props.studios.filter( studio => { 
      let price = studio.price;
      while(price.charAt(0) === '$') {
       price = price.substr(1);
      }
      price = price.replace('Suggested Donation', '00.00')
      let parsedPrice = parseInt(price);
      newArr.push(parsedPrice)
      return newArr.sort((a,b) => (a - b));
    })
  }

【问题讨论】:

    标签: javascript reactjs higher-order-functions


    【解决方案1】:

    将您的值转换为数字。根据您的代码,您的建议价格应为 0,因此如果价格不以美元符号开头,我们将使用它'$'

    const studios = [
      {
        name: "Whole Yoga",
        price: "$17.00"
      },
      {
        name: "Rino Yoga Social",
        price: "Suggested Donation"
      },
      {
        name: "Samadhi Yoga",
        price: "$20.00"
      },
      {
        name: "Corepower Yoga",
        price: "$25.00"
      },
      {
        name: "The River Yoga",
        price: "$20.00"
      },
      {
        name: "Endorphin Yoga",
        price: "$10.00"
      },
      {
        name: "Kindness Yoga",
        price: "$20.00"
      },
      {
        name: "Yoga High",
        price: "$15.00"
      },
      {
        name: "Freyja Project",
        price: "$22.00"
      },
      {
        name: "Kula Yoga",
        price: "$17.00"
      }
     ]
    
    priceFilter = (vals) => {
      return vals.sort((a,b) => {
        const aPrice = a.price[0] === '$' ? parseFloat(a.price.slice(1,-1)) : 0;
        const bPrice = b.price[0] === '$' ? parseFloat(b.price.slice(1,-1)) : 0;
        return aPrice - bPrice;
      });
    }
    
    console.log(priceFilter(studios));

    【讨论】:

      【解决方案2】:

      您可以使用Array.prototype.sort (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 编写自定义排序。

      const compare = (a, b) => {
        const aPrice = Number(a.price.replace(/[^0-9.-]+/g,""));
        const bPrice = Number(b.price.replace(/[^0-9.-]+/g,""));
      
        return aPrice - bPrice
      };
      
      
      const sortedStudios = this.props.studios.sort(compare);
      

      【讨论】:

        【解决方案3】:

        您可以使用一个函数来获取排序值,然后将 delta 作为排序方法的 redsult。

        const getValue = ({ price }) => +price.slice(1) || 0;
        
        var studios = [{ name: "Whole Yoga", price: "$17.00" }, { name: "Rino Yoga Social", price: "Suggested Donation" }, { name: "Samadhi Yoga", price: "$20.00" }, { name: "Corepower Yoga", price: "$25.00" }, { name: "The River Yoga", price: "$20.00" }, { name: "Endorphin Yoga", price: "$10.00" }, { name: "Kindness Yoga", price: "$20.00" }, { name: "Yoga High", price: "$15.00" }, { name: "Freyja Project", price: "$22.00" }, { name: "Kula Yoga", price: "$17.00" }];
        
        studios.sort((a, b) => getValue(a) - getValue(b));
        
        console.log(studios);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

        • 这似乎不包括价格为“建议捐赠”的情况
        • @weilandia,抱歉没有看到这个。请参阅编辑。
        【解决方案4】:

        给你。 :)

        let studios = [{
            name: "Whole Yoga",
            price: "$17.00"
          },
          {
            name: "Rino Yoga Social",
            price: "Suggested Donation"
          },
          {
            name: "Samadhi Yoga",
            price: "$20.00"
          },
          {
            name: "Corepower Yoga",
            price: "$25.00"
          },
          {
            name: "The River Yoga",
            price: "$20.00"
          },
          {
            name: "Endorphin Yoga",
            price: "$10.00"
          },
          {
            name: "Kindness Yoga",
            price: "$20.00"
          },
          {
            name: "Yoga High",
            price: "$15.00"
          },
          {
            name: "Freyja Project",
            price: "$22.00"
          },
          {
            name: "Kula Yoga",
            price: "$17.00"
          }
        ];
        console.log("Unsorted", studios);
        
        studios.sort(({
          price: a
        }, {
          price: b
        }) => {
          //parseFloat will be Nan if it cannot parse the string into a number
          //the only problem here is that any non int string will turn into 0
          a = parseFloat(a.slice(1), 10) || 0;
          b = parseFloat(b.slice(1), 10) || 0;
        
          return a - b;
        });
        
        console.log("Sorted", studios);

        【讨论】:

        • 注意 parseInt 忽略小数
        【解决方案5】:

        您可能希望按价格而不是按价格排序对象:

        const studios = [{"name":"Whole Yoga","price":"$17.00"},{"name":"Rino Yoga Social","price":"Suggested Donation"},{"name":"Samadhi Yoga","price":"$20.00"},{"name":"Corepower Yoga","price":"$25.00"},{"name":"The River Yoga","price":"$20.00"},{"name":"Endorphin Yoga","price":"$10.00"},{"name":"Kindness Yoga","price":"$20.00"},{"name":"Yoga High","price":"$15.00"},{"name":"Freyja Project","price":"$22.00"},{"name":"Kula Yoga","price":"$17.00"}];
        
        const parsePrice = x => parseFloat(x.replace(/^\$/, '')) || 0
        const sortedStudios = studios
          .slice()
          .sort((a, b) => parsePrice(a.price) - parsePrice(b.price))
        
        console.log(sortedStudios)

        【讨论】:

          【解决方案6】:

          感谢大家的帮助!这个解决方案对我有用。

          priceFilter = () => {
              let ordered = studios.sort((a, b) => (a.price > b.price) ? 1 : -1);
              let lastElement = ordered.pop();
              return ordered.unshift(lastElement);
            }
          

          【讨论】: