将字符串数组排序为对象数组

Sort array of strings into array of objects

本文关键字:对象 数组 数组排序 字符串      更新时间:2023-09-26

好的,我一直在为我的应用程序编写排序函数,但是我遇到了问题。

这是我的小提琴。

为了简单地解释一下,这段代码从一个字符串数组serials和一个空数组displaySerials开始:
var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var displaySerials = [];

这些函数的目的是输出displaySerials作为具有两个属性的对象数组:beginSerialendSerial。这样做的目的是让函数循环遍历数组,并尝试在一个范围内相互设置每个兼容字符串,然后从该范围创建对象,其中beginSerial是范围内最低的序列号,endSerial是范围内最高的序列号。

为了澄清,连续范围内的所有序列都将具有相同的前缀。一旦建立了前缀,那么将字符串从前缀中分离出来,并对其进行比较和排序。

因此,基于此,数组serials的期望输出将是:
displaySerials = [
    { beginSerial: "BHU-008", endSerial: "BHU-011" },
    { beginSerial: "BHU-000", endSerial: "BHU-002" },
    { beginSerial: "TYU-969", endSerial: "TYU-970" }
]

我已经得到了它主要工作在我的jsfiddle,唯一的问题是,该函数是推一个重复的对象到数组中,我不确定它是如何管理通过我的检查。

Marc的解决方案是正确的,但是我忍不住认为代码太多了。这是做完全相同的事情,从sort()开始,然后使用reduce(),以获得更优雅的外观。

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"]
serials.sort()
var first = serials.shift()
var ranges = [{begin: first, end: first}]
serials.reduce(mergeRange, ranges[0])
console.log(ranges) // the expected result
// and this is the reduce callback:
function mergeRange(lastRange, s)
{
    var parts = s.split(/-/)
    var lastParts = lastRange.end.split(/-/)
    if (parts[0] === lastParts[0] && parts[1]-1 === +lastParts[1]) {
        lastRange.end = s
        return lastRange
    } else {
        var newRange = {begin: s, end: s}
        ranges.push(newRange)
        return newRange
    }
}

我有一种感觉,不需要排序就可以做到这一点,通过递归地合并在数组的小块上获得的结果(比较两个两个的元素,然后合并两个两个的结果,以此类推,直到你有一个单一的结果数组)。代码看起来不是很好,但它可以更好地扩展,并且可以并行完成。

这里没有太复杂的东西,但应该可以达到目的。请注意,我从一开始就对数组进行排序,以便可以可靠地遍历它。

小提琴在这里:http://jsfiddle.net/qyys9vw1/

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var myNewObjectArray = [];
var sortedSerials = serials.sort();
//seed the object
var myObject = {};
var previous = sortedSerials[0];
var previousPrefix = previous.split("-")[0];
var previousValue = previous.split("-")[1];
myObject.beginSerial = previous;
myObject.endSerial = previous;
//iterate watching for breaks in the sequence
for (var i=1; i < sortedSerials.length; i++) {
    var current = sortedSerials[i];
    console.log(current);
    var currentPrefix = current.split("-")[0];
    var currentValue = current.split("-")[1];
    if (currentPrefix === previousPrefix && parseInt(currentValue) === parseInt(previousValue)+1) {
        //sequential value found, so update the endSerial with it
        myObject.endSerial = current;
        previous = current;
        previousPrefix = currentPrefix;
        previousValue = currentValue;
    } else {
        //sequence broken; push the object
        console.log(currentPrefix, previousPrefix, parseInt(currentValue), parseInt(previousValue)+1);
        myNewObjectArray.push(myObject);
        //re-seed a new object
        previous = current;
        previousPrefix = currentPrefix;
        previousValue = currentValue;
        myObject = {};
        myObject.beginSerial = current;
        myObject.endSerial = current;
    }
}
myNewObjectArray.push(myObject); //one final push
console.log(myNewObjectArray);

我将使用underscore.js来表示

var bSerialExists = _.findWhere(displaySerials, { beginSerial: displaySettings.beginSerial });
var eSerialExists = _.findWhere(displaySerials, { endSerial: displaySettings.endSerial });
if (!bSerialExists && !eSerialExists)
    displaySerials.push(displaySettings);

我最终解决了我自己的问题,因为我比我想象的要接近得多。我包含了一个最终排序,以便在初始排序完成后消除重复的对象。

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var displaySerials = [];

var mapSerialsForDisplay = function () {
    var tempArray = serials;
    displaySerials = [];
    for (var i = 0; i < tempArray.length; i++) {
        // compare current member to all other members for similarity
        var currentSerial = tempArray[i];
        var range = [currentSerial];
        var displaySettings = {
            beginSerial: currentSerial,
            endSerial: ""
        }
        for (var j = 0; j < tempArray.length; j++) {
            if (i === j) {
                continue;
            } else {
                var stringInCommon = "";
                var comparingSerial = tempArray[j];
                for (var n = 0; n < currentSerial.length; n++) {
                    if (currentSerial[n] === comparingSerial[n]) {
                        stringInCommon += currentSerial[n];
                        continue;
                    } else {
                        var currentRemaining = currentSerial.replace(stringInCommon, "");
                        var comparingRemaining = comparingSerial.replace(stringInCommon, "");
                        if (!isNaN(currentRemaining) && !isNaN(comparingRemaining) && stringInCommon !== "") {
                            range = compareAndAddToRange(comparingSerial, stringInCommon, range);
                            displaySettings.beginSerial = range[0];
                            displaySettings.endSerial = range[range.length - 1];
                            var existsAlready = false;
                            for (var l = 0; l < displaySerials.length; l++) {

                                if (displaySerials[l].beginSerial == displaySettings.beginSerial || displaySerials[l].endSerial == displaySettings.endSerial) {
                                    existsAlready = true;
                                }
                            }
                            if (!existsAlready) {
                                displaySerials.push(displaySettings);
                            }
                        }
                    }
                }
            }
        }
    }
    for (var i = 0; i < displaySerials.length; i++) {
        for (var j = 0; j < displaySerials.length; j++) {
            if (i === j) {
                continue;
            } else {
                if (displaySerials[i].beginSerial === displaySerials[j].beginSerial && displaySerials[i].endSerial === displaySerials[j].endSerial) {
                    displaySerials.splice(j, 1);
                }
            }
        }
    }
    return displaySerials;
}
var compareAndAddToRange = function (candidate, commonString, arr) {
    var tempArray = [];
    for (var i = 0; i < arr.length; i++) {
        tempArray.push({
            value: arr[i],
            number: parseInt(arr[i].replace(commonString, ""))
        });
    }
    tempArray.sort(function(a, b) { 
        return (a.number > b.number) ? 1 : ((b.number > a.number) ? -1 : 0); 
    });
    var newSerial = {
        value: candidate,
        number: candidate.replace(commonString, "")
    }
    if (tempArray.indexOf(newSerial) === -1) {
        if (tempArray[0].number - newSerial.number === 1) {
            tempArray.unshift(newSerial)
        } else if (newSerial.number - tempArray[tempArray.length - 1].number === 1) {
            tempArray.push(newSerial);
        }
    }
    for (var i = 0; i < tempArray.length; i++) {
        arr[i] = tempArray[i].value;
    }
    arr.sort();
    return arr;
}
mapSerialsForDisplay();
console.log(displaySerials);

查看效果

下面是在纯JavaScript中完成此操作的函数:

var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
function transformSerials(a) {
  var result = []; //store array for result
  var holder = {}; //create a temporary object
  //loop the input array and group by prefix
  a.forEach(function(val) {
    var parts = val.split('-');
    var type = parts[0];
    var int = parseInt(parts[1], 10);
    
    if (!holder[type])
      holder[type] = { prefix : type, values : [] };
    
    holder[type].values.push({ name : val, value : int });
  });
  
  //interate through the temp object and find continuous values
  for(var type in holder) {
    var last = null;
    var groupHolder = {};
    
    //sort the values by integer
    var numbers = holder[type].values.sort(function(a,b) {
      return parseInt(a.value, 10) > parseInt(b.value, 10);
    });
    
    numbers.forEach(function(value, index) {
      if (!groupHolder.beginSerial)
        groupHolder.beginSerial = value.name;
        
      if (!last || value.value === last + 1) {
        last = value.value;
        groupHolder.endSerial = value.name;
        if (index === numbers.length - 1) {
          result.push(groupHolder);
        }
      }
      else {
        result.push(groupHolder);
        groupHolder = {};
        last = null;
      }
    });
    
  }
  return result;
}
console.log(transformSerials(serials));
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>