我对编程还是比较陌生,并且有一个我正在从事的项目。我正在为一家虚构的披萨公司制作员工效率仪表板。我想找到最快的披萨制作时间,并向用户显示时间和工作人员姓名。
使用数据图表非常容易。创建一个函数,然后使用dc,例如dc.barChart(“#idOfDivInHtmlPage”)
我怀疑我可能试图变得太复杂,而我完全忘记了如何将js函数的任何输出显示到html页面。
我一直在使用d3.js,dc.js和crossfilter以交互方式直观地表示大多数数据。
.csv的代码段
private func globalApi401Handler(request: Siesta.Request) -> Request {
return request.chained { //special case to Refresh Token On Auth Failure
if case
.failure(let error) = $0.response, // Did request fail…
error.httpStatusCode == 401, // …because of expired token?
self.appSession != nil { // we have refreshToken
log.warning("Seems like Access Token is expired, Trying to refresh it!")
if self._tokenRefreshInProgress { //Should I use semaphore or other thread sync primitive here?
return .passTo(request.repeated()) //Another request is already trying to refresh. Retry until guard is cleared. Do we get new access token from decorators here?
} else {
self._tokenRefreshInProgress=true //set guard for other requests
return .passTo(
self.refreshAuth().chained { // first request a new token, then:
if case .failure = $0.response { // If token request failed…
return .useThisResponse // …report that error.
} else {
return .passTo(request.repeated()) // We have a new token! Repeat the original request.
}
}
)
}
}
if case
.failure(let error) = $0.response, // Did request fail…
error.httpStatusCode == 401, // …because of expired token?
self.appSession == nil || self.relogin == true { // appSession is new
self.onEvent.trigger(.Relogin)
return .useThisResponse
}
#warning("Use custom error unwrapper to conform API error reporting convention")
if case .failure(let error) = $0.response {
log.error("Got error: \(error.httpStatusCode ?? -1), unwrapping data...")
if let data = error.entity?.content as? Data {
log.error("Error data is: \(String(decoding: data, as: UTF8.self))")
} else {
log.error("Error data cannot be unwrapped")
}
}
return .useThisResponse // If not, use the response we got.
}
}
这是我到目前为止尝试过的:
mainlist=[['a',1,2],['b',3,6],['a',2,3],['b',6,9],['a',2,4],['b',4,8],['c',1,4],['c',4,7],['a',4,7]]
然后在HTML
outputlist=[['a',1,2],['b',3,6],['a',2,4],['c',1,4]]
答案 0 :(得分:0)
您肯定在正确的轨道上,但是在javascript中,您通常必须考虑事情发生的时间。
document.write()
(或更确切地说,脚本顶层的任何内容)将在页面加载时执行。
但是我敢打赌,您的数据是异步地加载的(可能是d3.csv
),因此您要等到稍后再使用交叉过滤器对象。您尚未显示这些部分,但这是使用交叉过滤器和dc.js的常用方法。
因此,您需要在页面加载后对其进行修改。 D3很棒! (执行此特定操作的直接javascript方法并不难。)
您应该能够将<p>
标签留在原处,删除多余的<script>
标签,然后在创建timeDim
的函数中:
d3.select('#minStaffPizzaTimeName').text(minStaffPizzaTimeName);
这会查找具有该ID的元素,并将其内容替换为您计算出的值。
您可以使用开发工具dom检查器来确保p
标签的ID为minStaffPizzaTimeName
。
您也可以使用
console.log(minStaffPizzaTimeName)
查看是否正确获取了数据。
没有一个运行中的示例很难说,但我认为您将只想使用PizzaTime定义维度,并将其从字符串转换为数字:
var timeDim = ndx.dimension(function(d) {
return +d.PizzaTime;
});
然后timeDim.bottom(1)[0]
应该为您提供原始数据中具有最低值PizzaTime
的行。将.Name
添加到该表达式应从行对象中检索名称字段。
但是您可能必须使用console.log
或交互式调试器来查找有效的确切表达式。如果没有这些工具,使用dc.js或D3几乎是不可能的,因此在学习它们方面的少量投资将为您节省大量时间。
答案 1 :(得分:0)
景气,终于明白了。
function show_fastest_and_slowest_pizza_maker(ndx) {
var timeDim = ndx.dimension(dc.pluck("PizzaTime"));
var minPizzaTimeName = timeDim.bottom(1)[0].Name;
var maxPizzaTimeName = timeDim.top(1)[0].Name;
d3.select('#minPizzaTimeName')
.text(minPizzaTimeName);
d3.select('#maxPizzaTimeName')
.text(maxPizzaTimeName);
}
非常感谢Gordon,您把我送上了正确的路!