在过去的四年中,我上了一所私立学校,这要求它的学生系领带。我发现找出前一天晚上衬衫,裤子和领带的组合是一件容易的事,因为有时这是一个乏味的过程。为了简化此过程,我想到了创建一个脚本来自动生成匹配衣服的新组合的想法。

到目前为止,我将所有衣服都输入到一个JSON文件中,并分成代表数组的数组类别(衬衫,裤子,领带)。每个数组的第一个元素是另一个数组,其中填充了该类别中的所有可用颜色/图案(红色,蓝色等)。对于每种颜色,都有一个由其颜色标识的数组ID,该数组ID描述了与该衬衫颜色对应的颜色/图案裤子/领带/毛衣。最后是一个数组,其中包含该颜色下每种服装的名称。万一您没有遵循其中的任何一个,这是我的JSON文件的一部分(在此处完整):我想不到更好的实现方式,因为匹配的衣服需要匹配多个标准。我创建随机组合的方法同样很乏味:可视化随机性。我最初的编码方法没有考虑到某些衬衫可以搭配某些领带,但是这些衬衫可能搭配没有领带或裤子的毛衣。因此,代码相当大。但是,我必须相信,对于我要实现的目标有更好的解决方案。另外,我想添加常规T恤的实现或与此相关的任何内容,但就目前而言,该结构过于严格,无法进行大量修改。

哦,是的,如果不清楚,代码取决于衬衫。因此,它会随机挑选一件衬衫,然后查看与之匹配的衬衫。如果代码不那么严格,那么能够以任何衣服(例如裤子)开头都很好。

评论

您可以发布一个jsfiddle演示进行测试吗?

@elclanrs当然可以!

#1 楼

好主意。我真的很喜欢您所做的事情,但是您的某些实现肯定可以改进。让我们从JSON开始。



其中一些数组是不需要的。您将每个clothes项目包装在[]中,由于阵列中只有一个项目,因此无需这样做!实际上,您应该只使用数组对like项进行分组。我也将摆脱您的颜色阵列,因为它似乎是多余的(稍后将对此进行详细介绍)。考虑这种重新设计;

"shirts": {
    "red": {
       "items": [ 
         "Red Flannel",
         "That Other Red Flannel"
       ],
       "matches": {
         "pants": [
           "navy",
           "khaki"
         ],
         "sweaters": [
           "navy",
           "grey"
         ],
         "ties": [
           "all"
         ]
       }
    }
}


您是否看到立即使我们能够更轻松地查找和迭代比赛的项目?您可以删除所有[0]访问器:

现在可以选择以下颜色:shirts[color],并使用进行迭代匹配;

 for (var match in shirts[color].matches) { 

 }


我到下一点。


您似乎在使用括号符号来访问对象中的项目。如果访问器不是变量,则可以使用点符号。

shirts[color]['matches'] === shirts[color].matches


区别有助于我们一目了然地区分访问属性的方式。 br />

函数randomArrayValue使用了不必要的eval。大部分时间都不需要评估,并且新JavaScript开发人员经常滥用它。您可以这样做;

function randomArrayValue(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}


除此之外,您还可以使用~~代替Math.floor,而且速度稍快。缺少许多var语句。这通常是不好的,因为没有var声明的变量被设置为全局变量,可以从任何地方访问。没有什么比全局变量错误更令人讨厌了。通过在程序顶部包含字符串'use strict';,可以通知此类问题。这告诉浏览器在编译时要严格一些。

考虑文字而不是新的Objects。例如:

combination = new Array(); // okay
combination = [];          // better

result = new Object(); // not great
result = {};           // awesome



对于结果对象,创建Object常量会更好;

var result = {
  shoes: randomArrayValue(pants[currentPantColor].shoes),
  pants: currentPantColor,
  sweater: currentSweaterColor,
  tie: currentTieColor
};
combination.push(result);



返回该颜色对象...您可以使用Object.keys(obj)获取对象的键。因此,如果您想知道衬衫进来的所有颜色,可以致电Object.keys(clothes.shirts)。如果要遍历所有颜色,则可以for...in

for (var colour in clothes.shirts) {
  var items = clothes.shirts[colour].items,
    matches = clothes.shirts[colour].matches;
}



首先就足够了,让我知道您是否想要指出如何在解决方案中利用其中的某些设计。

评论


\ $ \ begingroup \ $
我将深入阅读此内容,但有两点简单的内容:1.)我几个月前编写了这段代码,昨天重新发现之后,我看到我使用了eval,我绝对不知道为什么。我认为它是从早期版本2遗留下来的。)我也是最近才开始使用点表示法的
\ $ \ endgroup \ $
–查理
2014年2月9日15:15

\ $ \ begingroup \ $
我对代码的主要关注是关于添加其他服装。您看到在哪个解决方案中可以轻松添加更多功能吗?我将其视为不同的功能,每个功能都可以从列表中进行排序,然后我要做的就是将数据放入管道中,并为我提供相应的项目。
\ $ \ endgroup \ $
–查理
2014年2月9日在16:23

\ $ \ begingroup \ $
我最终进行了更改,它看起来更干净了。但是,该逻辑在某些地方仍然显得多余。
\ $ \ endgroup \ $
–查理
2014年2月9日在20:29

\ $ \ begingroup \ $
@Jivings关于改善逻辑的任何说法?
\ $ \ endgroup \ $
–查理
2014年7月11日下午5:10

#2 楼

为了完成您的要求,您需要将方法转换为功能方法,并大量重写代码。折叠的概念可以最好地解决您要找的问题。

检查它!

您调用一个函数来找到与您选择的衬衫匹配的函数。您说:“嘿,这是一件衬衫,给我找一些相配的裤子!”然后,它不仅返回一些匹配的裤子,而且还返回一个包含刚刚为您找到的衬衫和裤子的对象,这就是原因–然后,您转过身将该对象传递给相同的功能,说:“哟,这就是我已经到目前为止,我们已经找到了一个匹配的毛衣!”您的函数会为您到目前为止所拥有的内容添加一个随机匹配项,并返回您到目前为止的整个衣服,然后将其传递到下一个函数中。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

如果您使用此代码,则可以创建一个包含以下内容的数组您要检索的项目列表,然后对其调用reduce,例如["shirt", "tie", "sweater"].reduce(findMatches);,其中findMatches是您的回调函数。

这还具有将所有逻辑都放在一个位置的额外好处。而且,只要您的数据正确更新,添加新衣服就如同将字符串添加到数组一样简单!