如何对具有动态属性的数组进行排序?

时间:2018-11-02 02:40:59

标签: javascript arrays reactjs sorting properties

我正在尝试根据标记为“ path”的动态值对电影进行排序,该动态值根据当前值计算为“ title”,“ genre.name”,“ numberInStock”或“ dailyRentalRate”州。但是,由于movies数组中的'genre'属性是一个对象,而不是其他字符串,因此我编写的compare函数尝试访问movieA(“ genre.name”)和movieB(“ genre.name”)。我认为此语法可能有效,但无效。当然,必须有一种优雅的方式来编写我的比较函数,它不需要仅在path设置为“ genre.name”时添加更多条件吗?非常感谢任何帮助或见解。谢谢(下面是一些代码片段)

var movies = [
    {
        title: "Terminator",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 6,
        dailyRentalRate: 2.5,
    },
    {
        title: "Die Hard",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 5,
        dailyRentalRate: 2.5
    },
    {
        title: "Get Out",
        genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
        numberInStock: 8,
        dailyRentalRate: 3.5
    }
]

this.state = {
    path: "title"  //'title' or 'genre.name' or 'numberInStock' or 'dailyRentalRate'
};

myCompare = (a, b) => {
    const path  = this.state.path;

    if (a[path] < b[path]) return - 1;
    if (a[path] > b[path]) return 1;
    return 0;
}

const moviesSorted = movies.sort(this.myCompare);

2 个答案:

答案 0 :(得分:2)

当路径中包含句点时,应将其转换为带有split的数组,然后使用reduce对其进行迭代并找到您要按其排序的嵌套值:

var movies = [
    {
        title: "foo bar",
        genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
        numberInStock: 8,
        dailyRentalRate: 3
    },
    {
        title: "Terminator",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 6,
        dailyRentalRate: 2.5,
    },
    {
        title: "Die Hard",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 5,
        dailyRentalRate: 2
    },
    {
        title: "Get Out",
        genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
        numberInStock: 8,
        dailyRentalRate: 3.5
    }
];

let path = "title";

const getNested = (obj, path) => path.split('.').reduce((a, prop) => a[prop], obj);
const myCompare = (a, b) => {
  const aVal = getNested(a, path);
  return typeof aVal === 'string'
  ? aVal.localeCompare(getNested(b, path))
  : aVal - getNested(b, path);
};

// Sort by title:
movies.sort(myCompare);
console.log(movies);

// Sort by genre.name:
path = 'genre.name';
movies.sort(myCompare);
console.log(movies);

答案 1 :(得分:0)

可能您可以编写一个辅助函数来获取嵌套值,如下所示:

function getNestedValue(fieldName, item) {
    if (fieldName.includes('.')) {
        const keyArr = fieldName.split('.');
        let result = item;
        if (keyArr.length > 1) {
            for (const key of keyArr) {
                result = result[key];
            }

            return result;
        }
    }

    return item[fieldName];
}

myCompare = (a, b) => {
    const { path } = this.state.sortColumn;
    const valueA = getNestedValue(path, a);
    const valueB = getNestedValue(path, b)

    if (valueA < valueB) return - 1;
    if valueA > valueB) return 1;
    return 0;
}

比较给出的结果。