code: func DisplayablePorts(ports []types.Port) string {
  	type portGroup struct {
  		first uint16
  		last  uint16
  	}
  	groupMap := make(map[string]*portGroup)
  	var result []string
  	var hostMappings []string
  	var groupMapKeys []string
  	sort.Slice(ports, func(i, j int) bool {
  		return comparePorts(ports[i], ports[j])
  	})
  
  	for _, port := range ports {
  		current := port.PrivatePort
  		portKey := port.Type
  		if port.IP != "" {
  			if port.PublicPort != current {
  				hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type))
  				continue
  			}
  			portKey = fmt.Sprintf("%s/%s", port.IP, port.Type)
  		}
  		group := groupMap[portKey]
  
  		if group == nil {
  			groupMap[portKey] = &portGroup{first: current, last: current}
  			// record order that groupMap keys are created
  			groupMapKeys = append(groupMapKeys, portKey)
  			continue
  		}
  		if current == (group.last + 1) {
  			group.last = current
  			continue
  		}
  
  		result = append(result, formGroup(portKey, group.first, group.last))
  		groupMap[portKey] = &portGroup{first: current, last: current}
  	}
  	for _, portKey := range groupMapKeys {
  		g := groupMap[portKey]
  		result = append(result, formGroup(portKey, g.first, g.last))
  	}
  	result = append(result, hostMappings...)
  	return strings.Join(result, ", ")
  }
docs: // DisplayablePorts returns formatted string representing open ports of container
  // e.g. "0.0.0.0:80->9090/tcp, 9988/tcp"
  // it's used by command 'docker ps'