javascript - 编辑 JSON 对象 - 寻找更好的功能方法

标签 javascript functional-programming

我有一个带有设置的 JSON 对象,与此类似:

var settings = {
  tab1: {
    active: true,
    selectOrder: 1,
    selected: false
  },
  tab2: {
    active: true,
    selectOrder: 2,
    selected: false
  },
  tab3: {
    active: false,
    selectOrder: 0,
    selected: false
  }
};

现在,我的目标是将具有最低“selectedOrder”的事件元素的“selected”属性设置为“true”。在此示例中,我应该为“tab1”元素设置“selected”(“tab3”的 selectedOrder 为 0 但未激活)。

其背后的原因是根据其优先级(selectOrder)选择第一个事件选项卡。

我的解决方案是:

function selectFirstActiveTab(visibilitySettings) {
  var selected = 1000;
  var answer = jQuery.extend({}, visibilitySettings);
  Object.keys(answer).forEach((key) => {
    if (answer[key].active && answer[key].selectOrder <= selected) {
      selected = answer[key].selectOrder;
    }
  });

  Object.keys(answer).forEach((key) => {
    answer[key].selected = (answer[key].selectOrder === selected) ? true : false;
  });
  return answer;
};

虽然这个解决方案有效,但它似乎是一个糟糕的解决方案。

我的问题是:

  1. 是否有更好的“函数式编程”方法? (例如使用map/reduce等)

  2. 我觉得我的设置对象结构不佳。也许我应该选择一个对象数组而不是这个 JSON?选择这样的 JSON 的原因是为了更简单地绑定(bind)到我的模板(类似于“{{settins.tab1.selected}}” - 比在我的 html 中查找它更简单)。这里更好的方法应该是什么?

Here is the complete example in JSBIN

最佳答案

  1. 对于对象上的map和reduce,您可以使用Underscore :
function selectFirstActiveTab(visibilitySettings) {
  // Clone input, with selected set to false.
  var answer = _.mapObject(visibilitySettings, (item, key) => {
    return {active: item.active, selectOrder: item.selectOrder, selected: false};
  });

  // Find the min among all value.
  var minObj = _.reduce(answer, (min, item) => {
    return (item.active && item.selectOrder < min.selectOrder) ? item : min;
  }, {active: true, selectOrder: Number.MAX_SAFE_INTEGER});

  // Set min to selected.
  minObj.selected = true;
  return answer;
};

jsBin

或普通 JavaScript:

function selectFirstActiveTab(visibilitySettings) {
  var keys = Object.keys(visibilitySettings);

  // Create a cloned obj, like map
  var answer = {};
  keys.forEach((key) => {
    var cloneTarget = visibilitySettings[key];
    answer[key] = {
      active: cloneTarget.active,
      selectOrder: cloneTarget.selectOrder,
      selected: false
    };
  });

  // Convert key => value map to an array of value, then reduce it to find min.
  var minimun = keys.map((key) => answer[key]).reduce((min, item) => {
    return (item.active && item.selectOrder < min.selectOrder) ? item : min;
  }, {active: true, selectOrder: Number.MAX_SAFE_INTEGER});

  // Set min to selected.
  minimun.selected = true;
  return answer;
};

jsBin

  • 它不是 JSON,它只是一个带有一些键值映射的普通 Object,我们将其用作 Map。如果输入是一个数组,则应用上述逻辑可能会更容易:
  • var settings = [
      {
        name: 'tab1',
        active: true,
        selectOrder: 1,
        selected: false
      },
      {
        name: 'tab2',
        active: true,
        selectOrder: 2,
        selected: false
      },
      {
        name: 'tab3',
        active: false,
        selectOrder: 0,
        selected: false
      }
    ];
    

    由于原生 javascript 支持在数组上进行归约/映射。然而,像 lodash 这样的库一样多, underscore只需让reduce/map在对象上可用即可。你可以 只需选择最适合您需要的一个(因为有很多类似的库使您能够通过对象进行映射/减少)。

    关于javascript - 编辑 JSON 对象 - 寻找更好的功能方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33328500/

    相关文章:

    python - 透明地将数字类型处理为单值序列(反之亦然)

    functional-programming - Scheme中的树数据结构算法?

    haskell - 当累加器满足特定条件时,如何从haskell中的折叠函数中突破?

    javascript - 减少按钮 HTML/CSS 中的文本

    javascript - 如何在 JavaScript 中访问 Rails 路由/URL?

    javascript - 字符串双循环的组合 (JavaScript)

    java - 如何在 Java 中迭代以下格式的日期范围 25-12-2012 到 31-12-2012(应保留连字符)?

    javascript - 单击 h :commandLink causes Uncaught ReferenceError: mojarra is not defined

    recursion - 尾递归调用尾递归

    java - 减少对象列表中的整数属性