Java 如何按最近值对列表排序
因此,我有一个小列表,如下所示,代表仓库位置:Java 如何按最近值对列表排序,java,android,sorting,Java,Android,Sorting,因此,我有一个小列表,如下所示,代表仓库位置: 30 09 05 30 04 05 30 02 01 31 07 05 31 07 04 31 03 05 31 03 06 31 09 05 31 02 05 第一列表示位置行,第二列表示位置高度,第三列表示位置位置(向前) 我需要计算叉车操作员根据不同位置检索不同物品的最佳路径(行、位置、高度) 为此,我使用Collection.sort首先按行对列表进行排序,然后按位置(向前),最后按高度对列表进行排序 行是成对分组的,因为操
30 09 05
30 04 05
30 02 01
31 07 05
31 07 04
31 03 05
31 03 06
31 09 05
31 02 05
第一列表示位置行,第二列表示位置高度,第三列表示位置位置(向前)
我需要计算叉车操作员根据不同位置检索不同物品的最佳路径(行、位置、高度)
为此,我使用Collection.sort首先按行对列表进行排序,然后按位置(向前),最后按高度对列表进行排序
行是成对分组的,因为操作员可以在不移动叉车位置和高度的情况下从偶数行(操作员左)和奇数行(操作员右)检索项目
我就快到了,我只需要一只手,当pos向前移动时,我需要保持相同的高度并获得最近的高度,而不是从底部开始,这会使操作员失去上下移动的时间
代码如下:
Collections.sort(unoptimizedLocations, new Comparator<ItemOrderLocation>() {
@Override
public int compare(ItemOrderLocation item1, ItemOrderLocation item2) {
int rowCmp = item1.row.compareTo(item2.row);
int heightCmp = item1.height.compareTo(item2.height);
int posCmp = item1.pos.compareTo(item2.pos);
int item1Row = Integer.parseInt(item1.row);
int item2Row = Integer.parseInt(item2.row);
boolean onForkLiftPath = false;
if (item1Row == (item2Row + 1) && (item2Row % 2 == 0)) {
onForkLiftPath = true;
}
if (!onForkLiftPath && rowCmp != 0) {
//Two differents rows which are not on Fork Lift Path
return rowCmp;
}
//If are on forklift path we compare the position
if (posCmp != 0) {
return posCmp;
}
//Lastly if row is on forklift path and we are on same position we need to sort by nearest height
return heightCmp;
}
});
public class ForkLiftOperator {
public static void main(String[] args) {
new ForkLiftOperator().start();
}
private void start() {
List<Location> locations = new ArrayList<Location>();
locations.add(new Location(30, 9, 5));
locations.add(new Location(30, 4, 5));
locations.add(new Location(30, 2, 1));
locations.add(new Location(31, 7, 5));
locations.add(new Location(31, 7, 4));
locations.add(new Location(31, 3, 5));
locations.add(new Location(31, 3, 6));
locations.add(new Location(31, 9, 5));
locations.add(new Location(31, 2, 5));
locations.add(new Location(32, 2, 5)); // Extra to simulate additional row/pair
List<Location> solution = solve(locations);
System.out.println(solution);
}
private List<Location> solve(List<Location> locations) {
List<Location> shortestPath = new ArrayList<Location>();
int activeRow, activePosition, activeHeight;
while ((activeRow = getNextRow(locations)) != 0) {
System.out.println("Working on row="+activeRow);
List<Location> activeLocations = getLocationsByRowPair(activeRow, locations);
activePosition = 0;
activeHeight = 0;
while ((activePosition = getNextPos(activePosition, activeLocations)) != 0) {
System.out.println("Working on pos="+activePosition);
List<Location> activePositionLocations = getLocationsForRowAndPosition(activeRow, activePosition, activeLocations);
shortestPath.addAll(minimizeHeight(activeHeight, activePositionLocations));
activeHeight = shortestPath.get(shortestPath.size()-1).height;
}
}
return shortestPath;
}
enum Direction { UP, DOWN }
/**
* For the given locations (which are guaranteed to be at the same row/position), minimize the total height change
* @param activePositionLocations The locations at this row/pair and location (they will only differ in height)
* @return The order will minimize the height change
*/
private List<Location> minimizeHeight(int currentHeight, List<Location> activePositionLocations) {
List<Location> optimizedHeightLocations = new ArrayList<Location>();
System.out.println("Processing locations="+activePositionLocations);
int minHeight = activePositionLocations.stream().mapToInt(location -> location.height).min().getAsInt();
int maxHeight = activePositionLocations.stream().mapToInt(location -> location.height).max().getAsInt();
/*
* There are only two options to minimize (if the current height falls between min and max):
* 1) Travel down then up
* 2) Travel up then down
*/
// First determine the first direction to go
Direction direction;
if (currentHeight == minHeight)
direction = Direction.UP;
else if (currentHeight == maxHeight)
direction = Direction.DOWN;
else {
int distanceUp = maxHeight-currentHeight;
int distanceDown = currentHeight-minHeight;
direction = distanceUp < distanceDown ? Direction.UP : Direction.DOWN;
}
// Now travel in that direction (must sort the correct way first
List<Location> sortedAscending = activePositionLocations.stream().sorted((l1, l2) -> Integer.compare(l1.height, l2.height)).collect(Collectors.toList());
List<Location> sortedDescending = activePositionLocations.stream().sorted((l1, l2) -> Integer.compare(l2.height, l1.height)).collect(Collectors.toList());
if (direction == Direction.UP) {
optimizedHeightLocations.addAll(sortedAscending.stream().filter(location -> location.height >= currentHeight).collect(Collectors.toList()));
optimizedHeightLocations.addAll(sortedDescending.stream().filter(location -> location.height < currentHeight).collect(Collectors.toList()));
} else { // Direction = DOWN
optimizedHeightLocations.addAll(sortedDescending.stream().filter(location -> location.height <= currentHeight).collect(Collectors.toList()));
optimizedHeightLocations.addAll(sortedAscending.stream().filter(location -> location.height > currentHeight).collect(Collectors.toList()));
}
return optimizedHeightLocations;
}
/**
* Determine all the locations for this current row/pair and position
* @param activeRow The current row/pair
* @param activePos The current position
* @param locations The locations for this row/pair
* @return The locations at this exact row/pair and position
*/
private List<Location> getLocationsForRowAndPosition(int activeRow, int activePos,
List<Location> locations) {
int minRow = activeRow;
int maxRow = ((activeRow & 1) == 0) ? activeRow + 1 : activeRow; // If even, then pair includes the next higher row
return locations.stream().filter(location -> location.row >= minRow && location.row <= maxRow && location.position == activePos)
.collect(Collectors.toList());
}
/**
* Determine the next position, given the current position
* @param currentPosition Where the operator is currently
* @param locations The locations for this row/pair
* @return The next closest, or zero if they are at the end
*/
private int getNextPos(int currentPosition, List<Location> locations) {
if (locations.isEmpty())
return 0;
OptionalInt min = locations.stream().filter(location -> location.position > currentPosition)
.mapToInt(location -> location.position)
.min();
return min.isPresent() ? min.getAsInt() : 0;
}
/**
* Filter out any locations for this row pair.
* The locations for this row will be removed from the original list
* @param nextRow The current row being processed
* @param locations The remaining locations
* @return The locations for the active row
*/
private List<Location> getLocationsByRowPair(int nextRow, List<Location> locations) {
List<Location> activeLocations = new ArrayList<Location>();
Iterator<Location> i = locations.iterator();
int minRow = nextRow;
int maxRow = ((nextRow & 1) == 0) ? nextRow + 1 : nextRow; // If even, then pair includes the next higher row
while (i.hasNext()) {
Location current = i.next();
if (current.row >= minRow && current.row <= maxRow) {
activeLocations.add(current);
i.remove();
}
}
return activeLocations;
}
/**
* Determine the lowest row from the locations provided
* @param locations All remaining locations
* @return The minimum row number remaining
*/
private int getNextRow(List<Location> locations) {
if (locations.isEmpty())
return 0;
return locations.stream().mapToInt(location -> location.row)
.min().getAsInt();
}
class Location {
final int row;
final int position;
final int height;
public Location(int row, int height, int position) {
this.row = row;
this.position = position;
this.height = height;
}
@Override
public String toString() {
return "[" + row + ", " + height + ", " + position + "]";
}
}
为了更好地理解最终排序列表(最接近的高度用于较小的高度移动),应如下所示:
30 02 01
31 07 04
31 02 05
31 03 05
30 04 05
31 07 05
30 09 05
31 09 05
31 03 06
30 02 01
31 07 04
31 07 05
30 09 05
31 09 05
30 04 05
31 03 05
31 02 05
31 03 06
你知道如何使用我的排序算法来达到这个结果吗?下面给出了限制条件,解决了叉车问题
ALGORITHM
Input: All locations
Output: Shortest path given constraints
1. For all row/pairs, in increasing order
2. For all positions in that row, in increasing order
3. For all heights with same row/pair and position, add locations to minimize the height change given a starting height
代码使用Java8流。代码试图使用单一用途的方法;因此,请随意用更熟悉的语法重写任何方法。它不能保证被优化,但考虑到输入的低大小,这不应该成为一个问题。如果你有任何问题,请告诉我
以及守则:
Collections.sort(unoptimizedLocations, new Comparator<ItemOrderLocation>() {
@Override
public int compare(ItemOrderLocation item1, ItemOrderLocation item2) {
int rowCmp = item1.row.compareTo(item2.row);
int heightCmp = item1.height.compareTo(item2.height);
int posCmp = item1.pos.compareTo(item2.pos);
int item1Row = Integer.parseInt(item1.row);
int item2Row = Integer.parseInt(item2.row);
boolean onForkLiftPath = false;
if (item1Row == (item2Row + 1) && (item2Row % 2 == 0)) {
onForkLiftPath = true;
}
if (!onForkLiftPath && rowCmp != 0) {
//Two differents rows which are not on Fork Lift Path
return rowCmp;
}
//If are on forklift path we compare the position
if (posCmp != 0) {
return posCmp;
}
//Lastly if row is on forklift path and we are on same position we need to sort by nearest height
return heightCmp;
}
});
public class ForkLiftOperator {
public static void main(String[] args) {
new ForkLiftOperator().start();
}
private void start() {
List<Location> locations = new ArrayList<Location>();
locations.add(new Location(30, 9, 5));
locations.add(new Location(30, 4, 5));
locations.add(new Location(30, 2, 1));
locations.add(new Location(31, 7, 5));
locations.add(new Location(31, 7, 4));
locations.add(new Location(31, 3, 5));
locations.add(new Location(31, 3, 6));
locations.add(new Location(31, 9, 5));
locations.add(new Location(31, 2, 5));
locations.add(new Location(32, 2, 5)); // Extra to simulate additional row/pair
List<Location> solution = solve(locations);
System.out.println(solution);
}
private List<Location> solve(List<Location> locations) {
List<Location> shortestPath = new ArrayList<Location>();
int activeRow, activePosition, activeHeight;
while ((activeRow = getNextRow(locations)) != 0) {
System.out.println("Working on row="+activeRow);
List<Location> activeLocations = getLocationsByRowPair(activeRow, locations);
activePosition = 0;
activeHeight = 0;
while ((activePosition = getNextPos(activePosition, activeLocations)) != 0) {
System.out.println("Working on pos="+activePosition);
List<Location> activePositionLocations = getLocationsForRowAndPosition(activeRow, activePosition, activeLocations);
shortestPath.addAll(minimizeHeight(activeHeight, activePositionLocations));
activeHeight = shortestPath.get(shortestPath.size()-1).height;
}
}
return shortestPath;
}
enum Direction { UP, DOWN }
/**
* For the given locations (which are guaranteed to be at the same row/position), minimize the total height change
* @param activePositionLocations The locations at this row/pair and location (they will only differ in height)
* @return The order will minimize the height change
*/
private List<Location> minimizeHeight(int currentHeight, List<Location> activePositionLocations) {
List<Location> optimizedHeightLocations = new ArrayList<Location>();
System.out.println("Processing locations="+activePositionLocations);
int minHeight = activePositionLocations.stream().mapToInt(location -> location.height).min().getAsInt();
int maxHeight = activePositionLocations.stream().mapToInt(location -> location.height).max().getAsInt();
/*
* There are only two options to minimize (if the current height falls between min and max):
* 1) Travel down then up
* 2) Travel up then down
*/
// First determine the first direction to go
Direction direction;
if (currentHeight == minHeight)
direction = Direction.UP;
else if (currentHeight == maxHeight)
direction = Direction.DOWN;
else {
int distanceUp = maxHeight-currentHeight;
int distanceDown = currentHeight-minHeight;
direction = distanceUp < distanceDown ? Direction.UP : Direction.DOWN;
}
// Now travel in that direction (must sort the correct way first
List<Location> sortedAscending = activePositionLocations.stream().sorted((l1, l2) -> Integer.compare(l1.height, l2.height)).collect(Collectors.toList());
List<Location> sortedDescending = activePositionLocations.stream().sorted((l1, l2) -> Integer.compare(l2.height, l1.height)).collect(Collectors.toList());
if (direction == Direction.UP) {
optimizedHeightLocations.addAll(sortedAscending.stream().filter(location -> location.height >= currentHeight).collect(Collectors.toList()));
optimizedHeightLocations.addAll(sortedDescending.stream().filter(location -> location.height < currentHeight).collect(Collectors.toList()));
} else { // Direction = DOWN
optimizedHeightLocations.addAll(sortedDescending.stream().filter(location -> location.height <= currentHeight).collect(Collectors.toList()));
optimizedHeightLocations.addAll(sortedAscending.stream().filter(location -> location.height > currentHeight).collect(Collectors.toList()));
}
return optimizedHeightLocations;
}
/**
* Determine all the locations for this current row/pair and position
* @param activeRow The current row/pair
* @param activePos The current position
* @param locations The locations for this row/pair
* @return The locations at this exact row/pair and position
*/
private List<Location> getLocationsForRowAndPosition(int activeRow, int activePos,
List<Location> locations) {
int minRow = activeRow;
int maxRow = ((activeRow & 1) == 0) ? activeRow + 1 : activeRow; // If even, then pair includes the next higher row
return locations.stream().filter(location -> location.row >= minRow && location.row <= maxRow && location.position == activePos)
.collect(Collectors.toList());
}
/**
* Determine the next position, given the current position
* @param currentPosition Where the operator is currently
* @param locations The locations for this row/pair
* @return The next closest, or zero if they are at the end
*/
private int getNextPos(int currentPosition, List<Location> locations) {
if (locations.isEmpty())
return 0;
OptionalInt min = locations.stream().filter(location -> location.position > currentPosition)
.mapToInt(location -> location.position)
.min();
return min.isPresent() ? min.getAsInt() : 0;
}
/**
* Filter out any locations for this row pair.
* The locations for this row will be removed from the original list
* @param nextRow The current row being processed
* @param locations The remaining locations
* @return The locations for the active row
*/
private List<Location> getLocationsByRowPair(int nextRow, List<Location> locations) {
List<Location> activeLocations = new ArrayList<Location>();
Iterator<Location> i = locations.iterator();
int minRow = nextRow;
int maxRow = ((nextRow & 1) == 0) ? nextRow + 1 : nextRow; // If even, then pair includes the next higher row
while (i.hasNext()) {
Location current = i.next();
if (current.row >= minRow && current.row <= maxRow) {
activeLocations.add(current);
i.remove();
}
}
return activeLocations;
}
/**
* Determine the lowest row from the locations provided
* @param locations All remaining locations
* @return The minimum row number remaining
*/
private int getNextRow(List<Location> locations) {
if (locations.isEmpty())
return 0;
return locations.stream().mapToInt(location -> location.row)
.min().getAsInt();
}
class Location {
final int row;
final int position;
final int height;
public Location(int row, int height, int position) {
this.row = row;
this.position = position;
this.height = height;
}
@Override
public String toString() {
return "[" + row + ", " + height + ", " + position + "]";
}
}
公共类ForkLiftOperator{
公共静态void main(字符串[]args){
新的ForkLiftOperator().start();
}
私有void start(){
列表位置=新的ArrayList();
位置。添加(新位置(30、9、5));
位置。添加(新位置(30、4、5));
位置。添加(新位置(30,2,1));
增加(新地点(31、7、5));
增加(新地点(31、7、4));
位置。添加(新位置(31,3,5));
位置。添加(新位置(31,3,6));
增加(新地点(31、9、5));
位置。添加(新位置(31,2,5));
locations.add(新位置(32,2,5));//额外模拟额外的行/对
列出解决方案=解决(位置);
System.out.println(解决方案);
}
私有列表求解(列表位置){
List shortestPath=new ArrayList();
int activeRow、activePosition、activeHeight;
而((activeRow=getNextRow(位置))!=0){
System.out.println(“处理行=“+activeRow”);
List activeLocations=getLocationsByRowPair(activeRow,位置);
活动位置=0;
活动高度=0;
而((activePosition=getNextPos(activePosition,activeLocations))!=0){
System.out.println(“在pos=“+activePosition上工作”);
List activePositionLocations=GetLocationsErrorAndPosition(activeRow、activePosition、activeLocations);
addAll(最小高度(activeHeight,activePositionLocations));
activeHeight=shortestPath.get(shortestPath.size()-1).height;
}
}
返回最短路径;
}
枚举方向{向上,向下}
/**
*对于给定位置(保证位于同一行/位置),将总高度变化降至最低
*@param activePositionLocations此行/对的位置和位置(它们仅在高度上不同)
*@返回订单将最小化高度变化
*/
私有列表最小高度(int currentHeight,List activePositionLocations){
List optimizedHeightLocations=new ArrayList();
System.out.println(“处理位置=“+activePositionLocations”);
int minHeight=activePositionLocations.stream().mapToInt(位置->位置.height).min().getAsInt();
int maxHeight=activePositionLocations.stream().mapToInt(位置->位置.height).max().getAsInt();
/*
*只有两个选项可最小化(如果当前高度介于“最小”和“最大”之间):
*1)向下移动,然后向上移动
*2)先上后下
*/
//首先确定要走的第一个方向
方向;
如果(当前高度==最小高度)
方向=向上的方向;
else if(currentHeight==maxHeight)
方向=方向。向下;
否则{
int distance up=最大高度currentHeight;
int distance down=当前高度最小高度;
方向=距离向上<距离向下?方向。向上:方向。向下;
}
//现在沿该方向行驶(必须先按正确的方式排序
List sortedAscending=activePositionLocations.stream().sorted((l1,l2)->Integer.compare(l1.height,l2.height)).collect(Collectors.toList());
List SORTEDESCENDING=activePositionLocations.stream().sorted((l1,l2)->Integer.compare(l2.height,l1.height)).collect(Collectors.toList());
如果(方向==向上方向){
optimizedHeightLocations.addAll(sortedAscending.stream().filter(location->location.height>=currentHeight).collect(Collectors.toList());
optimizedHeightLocations.addAll(sortedDescending.stream().filter(location->location.heightlocation.height location.height>currentHeight).collect(Collector.toList());
}
返回优化的八个位置;
}
/**
*确定当前行/对和位置的所有位置
*@param activeRow当前行/对
*@param activePos当前位置
*@param locations此行/对的位置
*@返回此精确行/对和位置的位置
*/
私有列表GetLocationsErrorAndPosition(int activeRow、int activePos、,
(列出地点){
int minRow=activeRow;
int maxRow=((activeRow&1)==0)?activeRow+1:activeRow;//如果为偶数,则该对包括下一个更高的行
返回locations.stream().filter(location->location.row>=minRow&&loca
private int getNextPos(int currentPosition, List<Location> locations) {
if (locations.isEmpty())
return 0;
OptionalInt min = locations.stream().filter(location -> location.position > currentPosition)
.mapToInt(location -> location.position)
.min();
return min.isPresent() ? min.getAsInt() : 0;
}
private int getNextPos(int currentPosition, List<Location> locations) {
if (locations.isEmpty())
return 0;
int minValue = Integer.MAX_VALUE;
for (Location location : locations) {
if (location.position > currentPosition && location.position < minValue)
minValue = location.position;
}
return minValue == Integer.MAX_VALUE ? 0 : minValue;
}
private int getNextRow(List<Location> locations) {
if (locations.isEmpty())
return 0;
return locations.stream().mapToInt(location -> location.row)
.min().getAsInt();
}
private int getNextRow(List<Location> locations) {
if (locations.isEmpty())
return 0;
int minValue = Integer.MAX_VALUE;
for (Location location : locations) {
if (location.row < minValue)
minValue = location.row;
}
return minValue;
}
private List<Location> minimizeHeight(int currentHeight, List<Location> activePositionLocations) {
List<Location> optimizedHeightLocations = new ArrayList<Location>();
int minHeight = Integer.MAX_VALUE;
int maxHeight = Integer.MIN_VALUE;
for (Location location : activePositionLocations) {
if (location.height < minHeight)
minHeight = location.height;
if (location.height > maxHeight)
maxHeight = location.height;
}
/*
* There are only two options to minimize (if the current height falls between min and max):
* 1) Travel down then up
* 2) Travel up then down
*/
// First determine the first direction to go
Direction direction;
if (currentHeight == minHeight)
direction = Direction.UP;
else if (currentHeight == maxHeight)
direction = Direction.DOWN;
else {
int distanceUp = maxHeight-currentHeight;
int distanceDown = currentHeight-minHeight;
direction = distanceUp < distanceDown ? Direction.UP : Direction.DOWN;
}
// Now travel in that direction (must sort the correct way first
List<Location> sortedAscending = new ArrayList<Location>(activePositionLocations); // Clone it
Collections.sort(sortedAscending, new Comparator<Location>() {
@Override
public int compare(Location l1, Location l2) {
return Integer.compare(l1.height, l2.height);
}
});
List<Location> sortedDescending = new ArrayList<Location>(activePositionLocations); // Clone it
Collections.sort(sortedDescending, new Comparator<Location>() {
@Override
public int compare(Location l1, Location l2) {
return Integer.compare(l2.height, l1.height);
}
});
if (direction == Direction.UP) {
for (Location location : sortedAscending) {
if (location.height >= currentHeight)
optimizedHeightLocations.add(location);
}
for (Location location : sortedDescending) {
if (location.height < currentHeight)
optimizedHeightLocations.add(location);
}
} else { // Direction = DOWN
for (Location location : sortedDescending) {
if (location.height <= currentHeight)
optimizedHeightLocations.add(location);
}
for (Location location : sortedAscending) {
if (location.height > currentHeight)
optimizedHeightLocations.add(location);
}
}
return optimizedHeightLocations;
}