通过嵌套值

时间:2018-01-12 15:26:36

标签: javascript algorithm sorting

我试图编写一个算法,用于通过对象中的值对数组中的对象进行排序。这显然很容易,但是我试图使函数变得灵活,因此它将按照我传入的任何值排序作为第一个参数。

所以我想说我有以下数据结构:

var data = [
  {
    employee: {
      age: 12,
      paylevel: {
        plevel: '2'
      }
    }
  },
  {
    employee: {
      age: 19,
      paylevel: {
        level: '1'
      }
    }
  }
]

我希望能够调用下面所示的函数,并对任何给定的值进行排序,并按特定的传入值进行排序。

sort('level', data);

sort('age', data);

以下是我的工作版本:

function sort(prop, data) {
  var key = prop;
  var parts = [];

  function _r(data) {
    if (Array.isArray(data)) {
      for (var i = 0; i < data.length; i++) {
        _r(data[i]);
      }
    } else if (typeof data === 'object') {
      for (var property in data) {
        if (data.hasOwnProperty(property) && parts.indexOf(property) === -1) {
          if (property === key) {
            parts.push(property);
            break;
          } else {
            if (typeof data[property] === 'object') parts.push(property);
            _r(data[property]);
          }
        }
      }
    }
  }

  _r(data);

  data.sort((a, d) => {
    var i = 0;
    while (i < parts.length) {
      a = a[parts[i]];
      d = d[parts[i]];
      i++;
    }
    return a - d;
  });

  return data;
}

var res = sort('glevel', data); 

我基本上使用递归函数来尝试构建树结构,然后将其传递给传入的键,同时将父键添加到数组中,以便稍后用于排序。

因此,如果我传入级别,递归函数(_r)将使用以下内容构建一个parts数组:

['employee', 'paylevel', 'level'] 

然后我使用它来通过使用while循环循环到数据结构并将javascript排序方法应用于结果来对数组进行排序。这适用于给定的数据结构。但是,如果我采用当前数据结构并添加具有子键/值对的另一个对象,则会中断。因此,以下数据结构将破坏我的代码:

[
  {
    employee: {
      age: 12,
      paylevel: {
        level: '1'
      },
      grouplevel: {
        glevel: '1'
      }
    }
  },
  {
    employee: {
      age: 19,
      paylevel: {
        level: '3'
      },
      grouplevel: {
        glevel: '2'
      }
    }
  }
]

因为零件阵列现在看起来像这样:

['employee', 'paylevel', 'level', 'glevel']

将“glevel”键添加到数组基本上会破坏while循环识别要排序的正确项的能力。有没有办法获取给定的键并构建父对象的树结构,只包括父键:

我希望这不会令人困惑。谢谢。

1 个答案:

答案 0 :(得分:0)

  

是否有办法获取给定键并构建父对象的树结构并仅包含父键

编程的好处在于,如果你能用英语清楚地陈述你的问题,那么你很可能只是把它翻译成一个程序。做你说的话:

var parts = [];
function _r(data) {
    if (Array.isArray(data) && data.length > 0) {
        // I didn't understand why you looped through all elements
        // I think i'll just visit the first element
        // In fact it might be better to take this call out of the function
        return _r(data[0]);
    } else {
        for(var property in data) {
            if (data.hasOwnProperty(property)) {
                // assume that _r will return you a boolean
                // that tells you whether or not
                // key was found in this property
                var didIFindAKey = _r(data.property);
                // if yes, then add this property to parts
                if (didIFindAKey) {
                    // Note that we need to PRE-pend the property
                    // to the beginning of parts, due to the nature
                    // of the recursion
                    parts.unshift(property);
                    // make the assumption above come true:
                    //     return true since you have found the key
                    return true;
                }
            }
        }
        // make the assumption above come true:
        //     return false since no property found the key
        return false;
    }
}

我没有尝试过,所以很有可能包含小错误。希望你能得到这个想法,并使其成功。请随意在评论中提问,请务必指出任何错误,以便我能够纠正我的答案。