カテゴリー
C++

C++ でstd::vectorをsortする

C++でstd::vectorを特定の順番でソートするsample code

例1 strings

void sortGuitarVoicingTypes() {
  std::vector<juce::String> order = {"Drop 2", "Drop 3", "Drop 2 & 3", "Drop 2 & 4", "Drop x2 & 3", "Closed Voicing"};
  std::vector<juce::String> result;
  for (const auto& str : order) {
    auto it = std::find(guitarVoicingTypes.begin(), guitarVoicingTypes.end(), str);
    if (it != guitarVoicingTypes.end()) {
      result.push_back(str);
      guitarVoicingTypes.erase(it);
    }
  }
  std::sort(guitarVoicingTypes.begin(), guitarVoicingTypes.end());
  result.insert(result.end(), guitarVoicingTypes.begin(), guitarVoicingTypes.end());
  guitarVoicingTypes = result;
}

例2 Object

struct Voicing {
  Voicing() {}
  Voicing(int i, juce::StringRef name, juce::StringRef quality, std::vector<int> voices)
  : index(i), name(name), quality(quality), voices(voices) {}
  int index;
  juce::String name;
  juce::String quality;
  std::vector<int> voices;
 
};
  
struct compare {
  inline bool operator() (const Voicing& v1, const Voicing& v2)
  {
    // Define the ordering of the quality values
      const std::array<juce::String, 4> qualityOrder = {MINOR_NAME, MAJOR_NAME, MINOR_MAJOR_NAME, DOMINANT_NAME};

      // Compare the quality values
      auto lhsQualityIndex = std::distance(qualityOrder.begin(), std::find(qualityOrder.begin(), qualityOrder.end(), v1.quality));
      auto rhsQualityIndex = std::distance(qualityOrder.begin(), std::find(qualityOrder.begin(), qualityOrder.end(), v2.quality));
      
    if (lhsQualityIndex != qualityOrder.size() && rhsQualityIndex != qualityOrder.size()) {
      // If both qualities are in the qualityOrder array, compare their indices
      return lhsQualityIndex < rhsQualityIndex;
    } else if (lhsQualityIndex == qualityOrder.size() && rhsQualityIndex == qualityOrder.size()) {
      // If both qualities are not in the qualityOrder array, compare them alphabetically
      return v1.quality < v2.quality;
    } else if (lhsQualityIndex != rhsQualityIndex) {
      // If only one quality is in the qualityOrder array, it is considered greater than the other
      return lhsQualityIndex < rhsQualityIndex;
    } else {
      // If the quality values are the same, compare the indices
      return v1.index < v2.index;
    }
  }
};

このように使います。

// std::vector<Voicing> voicings {};
std::sort(voicings.begin(), voicings.end(), compare());