SOURCE

// ********************************************************************
// 工具函数
function splat(fun) {
  return function(array) {
    return fun.apply(null, array);
  };
}

function existy(x) {
  return x != null
};

function cat() {
  var head = _.first(arguments);
  if (existy(head)) return head.concat.apply(head, _.rest(arguments));
  else return [];
}

function construct(head, tail) {
  return cat([head], _.toArray(tail));
}

function second(arr) {
  return arr[1];
}
// ********************************************************************
// 具体实现
var influences = [['Lisp', 'Smalltalk'], ['Lisp', 'Scheme'], ['Smalltalk', 'Self'], ['Scheme', 'JavaScript'], ['Scheme', 'Lua'], ['Self', 'Lua'], ['Self', 'JavaScript']];

function wrap(graph, nodes, curNode) {
  var rs = {};
  function nexts(graph, node) {
    if (_.isEmpty(graph)) return [];

    var pair = _.first(graph);
    var from = _.first(pair);
    var to = second(pair);
    var more = _.rest(graph);

    if (_.isEqual(node, from)) return construct(to, nexts(more, node));
    else return nexts(more, node);
  }

  for (var i = 0; i < nodes.length; i++) {
    rs[nodes[i]] = nexts(graph, nodes[i]);
  }
  return rs;
}

var rs = wrap(influences, ['Lisp', 'Self']);
var str = JSON.stringify(rs);
console.log(str);
console 命令行工具 X clear

                    
>
console