2011年12月3日 星期六

前端處理JSON資料與陣列 - 使用 LINQ to JavaScript (2)


之前我們介紹了 LINQ to JavaScript (JSLINQ)的基本使用方式,而我們所下載的JSLINQ是2009年所發佈的版本,

在JSLINQ的Codeplex的網站上作者所簽入Source Code離最近一次的日期是 2010-11-13,

image

所以我們就來使用這Source Code裡最新版本的函式庫,新版本的函式庫中有新增了幾個function,

而我們就來看看這些新的function以及進行幾個進階操作。

 

LINQ to JavaScript (JSLINQ) Source Code

http://jslinq.codeplex.com/SourceControl/list/changesets

image

依據上面的連結進入到頁面後,點選「Lastest Version」的Download,下載後的壓縮檔把它解開,

image

選取壓縮檔中的兩個檔案:JSLINQ.js, JSLINQ-vsdoc.js,複製這兩個檔案之後再去覆蓋掉原本中所使用的檔案,

將原本的檔案給覆蓋掉之後,請記得要在VS2010中去更新JScript IntelliSense…

 

來看看新版本有多了哪些function:

image

比對一下之前的版本,這個 v 2.2的版本有多了幾個function:

Take, Skip, Each, Random

 


進階操作

接下來我們來操作以下幾種情境:

一、取得前10筆資料

二、依據OrderDate資料做排序,從最新到最舊(降冪排序 DESC)

三、取得這份Order資料中有哪些顧客下訂單

四、分頁

我們此次要使用的範例資料是Northwind中Orders:

image

欄位分別為:OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, ShipCountry


一、取得前10筆資料

在LINQ中我們要取得一個集合資料的前幾筆資料就是需要使用到Take()方法,而在JSLINQ也是一樣使用Take()方法,

直接來看看程式中使用Take()的方式:

function Button1Event()
{
  $('#OrderContent').html();
  var result = GetData();
  var data = new JSLINQ(result).Take(10).ToArray();
  var details = data.length + "<hr/>";
  $.each(data, function (i, item)
  {
    details += item["OrderID"] + "|" + item["CustomerID"] + "|" + item["EmployeeID"] + "|";
    details += item["OrderDate"] + "|" + item["ShippedDate"] + "|" + item["ShipCountry"] + "|" + "<br/>";
  });
  $('#OrderContent').html(details);
}

而執行結果:

image

 

二、依據OrderDate資料做排序,從最新到最舊(降冪排序 DESC)

JSLINQ對於排序也是一樣有提供兩種方法,一個是「OrderBy」另一個就是「OrderByDescending」前者是升冪而後者是降冪,

程式中使用的方式:

function Button2Event()
{
  $('#OrderContent').html();
  var result = GetData();
  var data = new JSLINQ(result)
    .OrderByDescending(function (item) { return item.OrderDate; })
    .Select(function (item) { return item; })
    .ToArray();
  var details = data.length + "<hr/>";
  $.each(data, function (i, item)
  {
    details += item["OrderID"] + "|" + item["CustomerID"] + "|" + item["EmployeeID"] + "|";
    details += item["OrderDate"] + "|" + item["ShippedDate"] + "|" + item["ShipCountry"] + "|" + "<br/>";
  });
  $('#OrderContent').html(details);
}

執行的結果:

image

可以與之前未做排序的資料做個比對(下圖),的確是有做到依據OrderDate做降冪排序的動作。

image

 

三、取得這份Order資料中有哪些顧客下訂單

原本應該是要使用Group by 的方式,但是JSLINQ並未提供這個方法,可以換個方式來看,其實也可以用Distinct()方法來取得結果,

另外除了使用Distinct()方法去取出不重複的CustomerID外,也使用Count()方法來取得每個CustomerID的訂單數量。

程式部分:

function Button3Event()
{
  $('#OrderContent').html();
  var result = GetData();
  var data = new JSLINQ(result).Distinct(function (item) { return item.CustomerID; }).ToArray();
  var details = data.length + "<hr/>";
  $.each(data, function (i, item)
  {
    var count = JSLINQ(result).Count(function (){ return this.CustomerID == item; });
    details += "CustomerID : " + item + " , count = " + count + "<br/>";
  });
  $('#OrderContent').html(details);
}
執行的結果:

image

 

四、分頁

在C#中,透過LINQ語法來做資料集合的分頁相當方便,使用Take()方法與Skip()方法就可以取得分頁的資料,

而在JSLINQ之中也是一樣,也是一樣使用Take()與Skip()方法,

首先我們的分頁操作介面如下:

image

每個分頁的資料量為15筆,以TextBox輸入頁碼,當輸入的頁碼為非數字或是空白時,將會預設顯示第一頁的資料,

當輸入的頁碼超過總頁數時,將會顯示最後一頁的分頁資料。

 

接下來就直接看程式的實作:

首先是計算分頁的總頁數function

function CalculatePageCount(totalCount, pageSize)
{
  var pageCount = 0;
  if (totalCount == 0)
  {
    pageCount = 0;
  }
  else
  {
    if ((totalCount % pageSize) == 0)
    {
      pageCount = totalCount / pageSize;
      if (pageCount < 1) pageCount = 1;
    }
    else
    {
      pageCount = parseInt((totalCount / pageSize).toFixed(0), 10) + 1;
    }
  }
  return pageCount;
}

接下來就是主要的程式內容:

function Button4Event()
{
  $('#OrderContent').html();
  var result = GetData();
  //預設每個分頁的資料量為15
  var pageSize = 15;
  //先取得全部的資料量
  var totalCount = new JSLINQ(result).Count();
  //計算取得分頁數
  var pageCount = CalculatePageCount(totalCount, pageSize);
  //取得頁碼
  var pageIndex = 1;
  if ($.trim($('#PageIndex').val()).length == 0)
  {
    pageIndex = 1;
  }
  else if (isNaN($('#PageIndex').val()))
  {
    pageIndex = 1;
  }
  else if($.trim($('#PageIndex').val()) != "1")
  {    
    pageIndex = parseInt($.trim($('#PageIndex').val()), 10);
    if(pageIndex > pageCount)
    {
       pageIndex = pageCount;
    }
    if(pageIndex < 1)
    {
      pageIndex = 1;
    }
  }
  $('#PageIndex').val(pageIndex);
  //取得分頁的資料, 以OrderID做升冪排序
  var data = new JSLINQ(result).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToArray();
  var details = data.length + "<hr/>";
  $.each(data, function (i, item)
  {
    details += item["OrderID"] + "|" + item["CustomerID"] + "|" + item["EmployeeID"] + "|";
    details += item["OrderDate"] + "|" + item["ShippedDate"] + "|" + item["ShipCountry"] + "|" + "<br/>";
  });
  $('#OrderContent').html(details);
}

就不用逐一解說程式的內容,

不過可以看一下取得分頁資料的部份,與我們在C#程式中使用LINQ的Skip() Take()方式來達成分頁的方式是一樣的,

以下是執行的畫面顯示:

顯示第一頁的分頁資料內容

image

顯示最後一頁的分頁資料內容:

image

顯示任意一頁的分頁資料內容

image


好的,我們都完成了四種情境的操作了,透過以上四種情境的程式實作的過程可以了解到在前端城市的環境中,

可以透過JSLINQ來達到如同在C#中的LINQ操作,所以前端集合資料的操作就不會在是一件麻煩事了。

 

另外在 GREG SHACKLES的Blog中有一篇文章對JSLINQ做了擴充的說明,

LINQ for JavaScript: Using and Extending JSLINQ

文章中有對原本的JSLINQ擴充了五種方法:

Take and TakeWhile, Skip and SkipWhile, ForEach

而其中Take, Skip, ForEach在新版的JSLINQ中都有了實作,而另外兩個TakeWhile()與SkipWhile()方法,有興趣的人可以自行前往了解。

 

那有關「LINQ for JavaScript (JSLINQ)」的介紹就到此為止,下一篇有關前端的LINQ-like語法的操作將會介紹另外其他的函式庫,

雖然有人覺得在前端程式中使用LINQ-like的操作是會對效能上有影響,

但我個人是覺得透過這些函式庫的幫助,可以讓程式設計人員更能夠掌握前端語言對於集合資料的操作,

畢竟現在的網站對於前端功能操作的需求是日益增多,有些操作在Client-Side完成會比再傳送到Server-Side處理更為直接與快速。

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。