Javascript排序数据



我有一个采用这种形状的对象数组。。。

type allRecipes = {
rows: [
{
category: string;
id: number;
owner: string;
recipes_uri: string;
recipes_name: string;
}
];
};

许多配方具有相同的recipes_namecategory,但具有不同的idownerrecipes_uri

我需要把这些整理成这个新的形状,这样可以消除一些重复,使数据更容易处理。

type recipesCollated = [
{
category: string;
recipes_name: string;
recipes_collection: [
{
id: number;
owner: string;
recipes_uri: string;
}
];
}
];

所以我试图在allRecipes.rows上循环,那么如果我使用.reduce,我已经在注释中删除了一些sudo代码。。。

const recipesCollated = [];
for (let i = 0; i < allRecipes.rows.length; i++) { 
// is allRecipes.rows[i].recipes_name in the recipesCollated array??;
// if its not push a new record in with one item in the recipes_collection array
// if it is, loop over recipesCollated.recipes_collection and check to see if the current id is in the array
// if it is, our job is done, if its not insert it into recipesCollated.recipes_collection array
}

与其检查是否包含在数组中(即O(n^2((,不如使用将类别和名称关联到条目数组的映射。如果需要,您可以随时将其转换为数组。例如:

const recipesCollated_ = new Map();
for (const recipe of recipes.rows) {
let category_map = recipesCollated_.get(recipe.category);
if (typeof category_map === 'undefined') {
const new_map = new Map();
recipesCollated_.set(recipe.category, new_map);
category_map = new_map;
}
let recipe_array = category_map.get(recipe.recipes_name);
if (typeof recipe_array === 'undefined') {
const new_arr = [];
category_map.set(recipe.recipes_name, new_arr);
recipe_array = new_arr;
}
recipe_array.push({ recipes_uri: recipe.recipes_uri, owner: recipe.owner, id: recipe.id, });
}
const recipesCollated = [];
for (const [ category, recipes_map, ] of recipesCollated_) {
for (const [ recipe_name, recipes, ] of recipes_map) {
recipesCollated.push({ recipes_name: recipe_name, category: category, recipes_collection: recipes, });
}
}

这可以通过使用相关属性的组合键进行分组的单个Array#reduce()调用来处理。

使用Map

const allRecipes = { rows: [{ category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 1', }, { category: 'cat 2', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 5', }, { category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 1', }, { category: 'cat 2', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 5', }, { category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 23', }], };
const collatedRecipes = [...allRecipes.rows.reduce((acc, { category, recipes_name, ...rest }) => {
const key = `${category}_${recipes_name}`;
if (acc.has(key)) {
acc.get(key).recipes_collection.push(rest);
} else {
acc.set(key, { category, recipes_name, recipes_collection: [rest] })
}
return acc;
}, new Map)
.values()]
console.log(collatedRecipes)
.as-console-wrapper { max-height: 100% !important; top: 0; }

object

const allRecipes = { rows: [{ category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 1', }, { category: 'cat 2', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 5', }, { category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 1', }, { category: 'cat 2', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 5', }, { category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 23', }], };
const collatedRecipes = Object
.values(allRecipes.rows
.reduce((acc, { category, recipes_name, ...rest }) => (
(acc[`${category}_${recipes_name}`] ??= { category, recipes_name, recipes_collection: [] })
.recipes_collection.push(rest), acc)
, {})
);
console.log(collatedRecipes)
.as-console-wrapper { max-height: 100% !important; top: 0; }

或者Mapfor...of环路

const allRecipes = { rows: [{ category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 1', }, { category: 'cat 2', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 5', }, { category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 1', }, { category: 'cat 2', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 5', }, { category: 'cat 1', id: 1, owner: 'Bill', recipes_uri: 'uri2', recipes_name: 'recipe 23', }], };
const collatedMap = new Map;
for (const { category, recipes_name, ...rest } of allRecipes.rows) {
const key = `${category}_${recipes_name}`;
if (collatedMap.has(key)) {
collatedMap.get(key).recipes_collection.push(rest);
} else {
collatedMap.set(key, { category, recipes_name, recipes_collection: [rest] });
}
}
const collatedArray = [...collatedMap.values()];
console.log(collatedArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

只需在原始数组上运行reduce方法,并检查名称和类别是否存在。如果是,则在现有对象中推送当前配方,否则在累积结果中添加一个新对象。

const recipes = {
rows: [
{
category: 'c1',
id: 1,
owner: 'o1',
recipes_uri: 'some url',
recipes_name: 'rn-1',
},
{
category: 'c1',
id: 2,
owner: 'o2',
recipes_uri: 'some url-2',
recipes_name: 'rn-1'
}
]
};
const result = recipes.rows.reduce((acc, cur) => {
const {recipes_name, category, ...recipe} = cur;
const recipeNameExist = acc.find(rec => rec.recipes_name === recipes_name);
const recipeCatExist = acc.find(rec => rec.category === category);
if(!(recipeCatExist && recipeNameExist)) {
acc.push({
recipes_name,
category,
recipes_collection: [recipe]
})
} else {
recipeCatExist.recipes_collection.push(recipe)
}
return acc;
}, []);
console.dir(result);
/*
[
{
recipes_name: 'rn-1',
category: 'c1',
recipes_collection: [
{ id: 1, owner: 'o1', recipes_uri: 'some url' },
{ id: 2, owner: 'o2', recipes_uri: 'some url-2' }
]
}
]
*/

工作REPL

最新更新