簡體   English   中英

對象數組的復雜排序

[英]Complex Sort for Array of Objects

因此,我已經從事此任務一段時間了,但遇到了一個問題。 我已經反復嘗試和重寫,似乎無法為此提供足夠好的解決方案。

我正在嘗試將一個對象數組排序為另一個對象數組。 我使用的是剔除法,但如果可以在香草JS或jQuery中更直接地進行剔除,則解決方案不必包含剔除法。

我會解釋:

我們從一個帶有一些序列號對象的observableArray serials開始。 該數組始終包含以下格式:

var serials = ko.observableArray([
    { number: "DFG09008", qty: 1 }, 
    { number: "DFG09009", qty: 1 },
    { number: "DFG09010", qty: 1 },
    { number: "DFG09011", qty: 1 },
    { number: "DFG09020", qty: 1 },
    { number: "ASD-0001", qty: 1 },
    { number: "ASD-0002", qty: 1 },
    { number: "HJ-DRT-06", qty: 1 },
    { number: "HJ-DRT-07", qty: 1 },
    { number: "POU055054", qty: 1 }
]);
// qty property is for something unrelated to this in the app

我正在編寫的函數的預期結果是,它將輸出到另一個observableArray displaySerials ,用於顯示“數值范圍”的概念:

var displaySerials = ko.observableArray([
    { beginSerial: "DFG09008", endSerial: "DFG09011" },
    { beginSerial: "DFG09020", endSerial: "" },
    { beginSerial: "ASD-0001", endSerial: "ASD-0002" },
    { beginSerial: "HJ-DRT-06", endSerial: "HJ-DRT-07" },
    { beginSerial: "POU055054", endSerial: "" }
]);

如此,因為serials '前四個成員的number屬性, "DFG09008", "DFG09009", "DFG09010", "DFG09011"有一個匹配的前綴( DFG090 ),並且是連續的后綴數字( 8, 9, 10, 11 ),它們被放入一個對象中,其中beginSerial是該范圍中的最低數字( DFG09008 ),而endSerial是最高的數字( DFG09011 )。 請注意, "DFG09020"放置在單獨的對象中。 這是因為它與組中的其他數字不連續,因此可以單獨考慮。

任何與組的其余部分無關的序列號都將放入其自己的對象中,其中endSerial屬性是一個空字符串: { beginSerial: "DFG09020", endSerial: "" }

序列號的結構唯一定義的規則是, 它們始終以數字結尾 但是集合中可能有數十或數百個。

上述內容以及以下內容僅是有效解決方案的要求:

  • 在此功能過程中,陣列serials應保持不變。
  • 解決方案不是特定的,也不依賴於串行的任何字符串結構,只是它們以數字結尾。

我的jsfiddle

任何貢獻都將不勝感激!

看起來您不需要它們進行分組那樣多的排序 他們似乎已經井然有序。 您所需要做的就是遍歷列表,查看每個列表是否與上一個列表相繼。 如果是,那就是您正在構建的displaySerial的結尾; 如果不是,則啟動一個新的displaySerial。

也許棘手的部分是確定它們是否是順序的。 我選擇使用正則表達式來分隔尾隨數字。 如果非數字部分相等且一個數字不同,則該序列是連續的。

在此不需要淘汰賽或jQuery。 您沒有對DOM做任何事情。 您可以使用實用程序功能,但沒有太多理由。 我已經使用了淘汰賽來顯示結果。

如果確實需要對它們進行排序,則可以使用具有相同正則表達式拆分器的比較功能,首先比較非數字部分,如果非數字相等,則比較數字。

 // test data var serials = [ { number: "DFG09008", qty: 1 }, { number: "DFG09009", qty: 1 }, { number: "DFG09010", qty: 1 }, { number: "DFG09011", qty: 1 }, { number: "DFG09020", qty: 1 }, { number: "ASD-0001", qty: 1 }, { number: "ASD-0002", qty: 1 }, { number: "HJ-DRT-06", qty: 1 }, { number: "HJ-DRT-07", qty: 1 }, { number: "POU055054", qty: 1 } ]; // constructor for displaySerials array function DisplaySerial (beginSerial, endSerial) { this.beginSerial = beginSerial; this.endSerial = endSerial; } var serialPartsPattern = /(.*\\D)(\\d+)$/; function isSequential(s1, s2) { if (s1 === undefined) return false; var m1 = s1.match(serialPartsPattern), m2 = s2.match(serialPartsPattern); return m1[1] === m2[1] && (+m1[2] + 1) === +m2[2]; } var displaySerials = [], currentSerial, prevSerial, currentDisplaySerial; for (var i=0; i<serials.length; ++i) { currentSerial = serials[i].number; if (isSequential(prevSerial, currentSerial)) { currentDisplaySerial.endSerial = currentSerial; } else { currentDisplaySerial = new DisplaySerial(currentSerial, ""); displaySerials.push(currentDisplaySerial); } prevSerial = currentSerial; } ko.applyBindings({displaySerials: displaySerials}); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <ol data-bind="foreach:displaySerials"> <li><span data-bind="text:beginSerial"></span>...<span data-bind="text:endSerial"></span></li> </ol> 

我正在附上基於lodash的解決方案。 我假設您的值不一定要排序。 請注意,我添加了更多值以正確顯示其排序和分組,並且更改了順序。

 var serials = [ { number: "DFG09008", qty: 1 }, { number: "DFG09009", qty: 1 }, { number: "DFG09016", qty: 1 }, { number: "DFG09010", qty: 1 }, { number: "DFG09011", qty: 1 }, { number: "DFG09005", qty: 1 }, { number: "DFG09014", qty: 1 }, { number: "DFG09015", qty: 1 }, { number: "DFG09020", qty: 1 }, { number: "ASD-0001", qty: 1 }, { number: "ASD-0002", qty: 1 }, { number: "HJ-DRT-06", qty: 1 }, { number: "HJ-DRT-07", qty: 1 }, { number: "POU055054", qty: 1 } ]; var splitSerials = _.map(serials, function(serial){ var parts = serial.number.match(/([^\\d]+)(\\d+)/); return {key: parts[1], number: parts[2]}; }); var grouped = _.groupBy(splitSerials, 'key'); function chunkConsec(array){ return _.transform(array, function(result, n){ if(_.last(_.last(result)) === n - 1){ _.last(result).push(n); } else { result.push([n]); } return true; }); } function unchunk(array){ if(array.length > 1){ return [_.first(array), _.last(array)]; } else { return array; } } var groupedArray = _.mapValues(grouped, _.flow( _.partial(_.map, _, 'number'), _.partial(_.map, _, _.parseInt), _.sortBy, chunkConsec, _.partial(_.map, _, unchunk) )); function buildRange(value, key){ var result = {beginSerial: (key + value[0])}; result.endSerial = (value.length > 1 ? key + value[1] : ''); return result; } function buildRanges(values, key){ return _.map(values, function(value){ return buildRange(value, key); }); } var finalResult = _.flatten(_.values(_.mapValues(groupedArray, buildRanges))); console.log(finalResult); alert(JSON.stringify(finalResult)); 
 <script src="https://cdn.rawgit.com/lodash/lodash/3.0.1/lodash.min.js"></script> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM