查询列表设计排序方案

    科技2023-11-28  110

    查询列表设计排序方案

    Like for many of you, the process of solving a coding challenge provides me a rich learning experience. It’s rarely a straight path, but the deviations, the ‘rabbit holes’, while not included in the final solution, frequently lead to a deeper understanding of the principals of coding. My latest project, and a particular (seemingly innocuous) feature I chose to add, leads me to this week’s exploration.

    像许多人一样,解决编码挑战的过程为我提供了丰富的学习经验。 它很少是一条直线路径,但是偏差(“兔子洞”)虽然未包含在最终解决方案中,但通常会导致人们对编码原理有更深入的了解。 我的最新项目以及我选择添加的特定功能(看似无害)使我进入了本周的探索。

    We’ve has been stuck at home the past months. Sound familiar? Cooking has become an important part of our lives. The first few weeks dinner time would arrive and we’d all stare at each other. No one had taken the initiative and there was nothing prepared and no restaurants to fall back on. Finally, we set a schedule so that each of us plans and cooks dinners for a full week. With three of us, this means one week of cooking intensity and two weeks of sitting back and enjoying the good eats (the dirty dishes are another matter). The outcome has been a marked improvement in the quality and variety of food we’ve been eating.

    过去几个月,我们一直呆在家里。 听起来有点熟? 烹饪已经成为我们生活中的重要组成部分。 最初几周的晚餐时间到了,我们都凝视着对方。 没有人主动采取行动,没有任何准备,也没有餐馆可供使用。 最后,我们制定了时间表,以便我们每个人计划和烹饪整整一周的晚餐。 对于我们三个人来说,这意味着一个星期的烹饪强度和两个星期的坐下来享受美味的食物(脏盘子是另一回事)。 结果是我们吃的食物的质量和种类有了明显的改善。

    When my turn comes around, I like to plan menus for the whole week and on Monday morning do all of the shopping so ingredients are at hand. Shopping is not high on my list of favorite activities so I like to get in and out fast. To help get me through, I decided to build an SPA shopping list that lets me enter in ingredients and quantities, and then display the sorted items on a list sorted by store section. With the sorted list, I can move through the sections quickly, confident I won’t have to return.

    轮到我时,我希望计划整周的菜单,而星期一早上则进行所有购物,因此食材就在手边。 购物在我喜欢的活动中并不算高,所以我喜欢快速进出。 为了帮助我理解,我决定建立一个SPA购物清单,让我输入配料和数量,然后在按商店部分排序的列表上显示排序的项目。 使用排序列表,我可以快速浏览各个部分,确信我不必返回。

    While the app will ultimately have an API to store lists, a master list, and allow others to login and use the app, I decided to focus on the React frontend first, using some seeded data to design and test. The interface is simple: a nav bar on top, two columns underneath — the Add Item form on the left and My List on the right. As you add items the app remembers the new items and brings them up as suggestions for next week’s list.

    虽然该应用程序最终将具有一个用于存储列表,主列表并允许其他人登录和使用该应用程序的API,但我还是决定首先关注React前端,使用一些种子数据进行设计和测试。 界面很简单:导航栏在顶部,下面两列-左侧的“添加项目”表单和右侧的“我的列表”。 添加项目时,应用程序会记住新项目,并将其作为下周列表的建议。

    The UI 用户界面

    The challenge came as I began to code ‘My List’: in particular, figuring out how to pull the headers from the sorted list. Here are a couple of solutions I came up with:

    我开始编写“我的列表”代码时遇到了挑战:特别是要弄清楚如何从已排序列表中提取标题。 这是我提出的几个解决方案:

    Build a custom sorted object each render of the list

    构建一个自定义的排序对象,每个呈现列表

    In this solution I take a basic array of item objects stored in the Redux store, and place them in an object with key : value pairs where the key is the category number (there is a lookup associating the category number with the actual category label) and the value is an array of items with equal categories.

    在此解决方案中,我使用Redux商店中存储的项目对象的基本数组,并将它们放置在具有key:value对的对象中,其中key是类别编号(存在将类别编号与实际类别标签相关联的查找)该值是具有相同类别的项目的数组。

    const sortList = () => { const sorted = {} const divs = [];// separate items into category objects curList.forEach(item => { if (!sorted[item.category]) { sorted[item.category] = [item]; } else { sorted[item.category].push(item); } })// iterate through each category object creating a <ListGroup/> component along with the category label and specific items for that category. for (let group in curList) { divs.push(<ListGroup category={group} items={curList[group] key={group} />); }return divs;}

    The <ListGroup/> component displays the category header and builds the individual <ListItem /> components.

    <ListGroup />组件显示类别标题并构建各个<ListItem />组件。

    This solution gets the job done, but I was concerned that the object has to be re-built every time the list is re-rendered (granted, not a deal breaker with such a small list), so I tried something else:

    该解决方案可以完成工作,但是我担心每次重新渲染列表时都必须重新构建对象(被授予,而不是这么小的列表来破坏交易),所以我尝试了其他方法:

    Building the sorted object directly in Redux store

    直接在Redux存储中构建排序的对象

    In this solution I build the sorted object directly in state as I dispatch new items to the reducer.

    在此解决方案中,当我将新项目分派给reducer时,我将直接在状态下构建已排序的对象。

    case 'ADD_TO_LIST':newList = Object.assign({}, state.curList) if (newList[action.payload.category]) { newList[action.payload.category].push(action.payload) } else { newList[action.payload.category] = [action.payload] }return { ...state, curList: newList }

    This solution worked as expected, building the object of categories in state which I then can access when building the ListGroups without having to build the sorted object every render. However, I discovered unexpected consequences down the road.

    此解决方案按预期工作,按状态构建类别的对象,然后在构建ListGroups时可以访问该状态,而不必构建每个渲染的排序对象。 但是,我发现了意想不到的后果。

    As it happens, I’ve included a boolean ‘status’ property in the items to allow users to cross out items they’ve already found. Clicking on a list item should dispatch an action that toggles the status. The problem is that reducers in Redux should not mutate state. Actually, Redux won’t throw an error if you mutate state directly. But, because old and new states are compared at a shallow level, mutating rather than replacing state won’t necessarily be registered as a change of state, and therefore components won’t know to re-render. Data is changed or added, but not reflected with an updated view. The problem is compounded when trying to modify a property that is deeply nested in state — in my case now, trying to update the property of an object (the item) within an array of items within an object (the category) within state. This is a hurdle that is inherent in Redux and is the reason that the Redux developers recommend keeping your data structure as flat as possible.

    碰巧的是,我在项目中包含了一个布尔值“ status”属性,以允许用户删除他们已经找到的项目。 单击列表项应调度一个切换状态的动作。 问题在于Redux中的reducer不应改变状态。 实际上,如果直接更改状态,Redux不会抛出错误。 但是,由于在浅层次上比较了新旧状态,因此更改(而不是替换)状态不一定要注册为状态变化,因此组件将不知道要重新渲染。 数据已更改或添加,但未反映在更新的视图中。 当尝试修改状态中深层嵌套的属性时,问题变得更加复杂-在我的情况下,尝试更新状态内对象(类别)中一系列项目中的对象(项目)的属性。 这是Redux固有的障碍,也是Redux开发人员建议保持数据结构尽可能平坦的原因。

    A third approach might be to do a simple sort of the items array by category and then at time of rendering, iterate through the array, checking to see when we reach a new category and rendering a new header. I think this approach would be the most susceptible to bugs caused by improperly formed data.

    第三种方法可能是按类别对项数组进行简单排序,然后在渲染时遍历数组,检查何时到达新类别并渲染新标题。 我认为这种方法最容易受到数据格式不正确导致的错误的影响。

    In the end, I chose to go with the first solution, although I’m sure there are other (maybe better) options out there. While this particular challenge was seemingly trivial, it allowed me to gain a better understanding of Redux, and more generally, how to work with objects in javascript. Our growth, as programmers, and humans, comes out of pushing ourselves to explore different options, sometimes the road less traveled. In doing so we gain knowledge and confidence, and exercise our ability to be creative. Bon Appetit!

    最后,尽管我确信还有其他(也许更好)的选择,但我选择了第一个解决方案。 尽管这个特殊的挑战看似微不足道,但它使我对Redux有了更深入的了解,并且更广泛地了解了如何使用javascript中的对象。 作为程序员和人类,我们的成长来自于推动自己去探索不同的选择,有时走的路很少。 通过这样做,我们获得了知识和信心,并发挥了创造力。 祝您好胃口!

    翻译自: https://medium.com/@rixong/designing-a-sorted-list-with-sub-headers-16d5010c162b

    查询列表设计排序方案

    相关资源:四史答题软件安装包exe
    Processed: 0.009, SQL: 8